I have sticky box with show hide button as shown in image. It is working but if I tried to hide there is horizontal scroll bar and can see the box as shown in image 2. To colapse the box, I change right-0 to -right-24. Is there anyway not to show the horizontal scroll bar.
Image 1 -: showing sticky bar and can click setting icon to hide the bar. There is no horizontal scroll bar.
Image 2 -: after hide the bar, horizontal scroll bar is appeared and can see the box when I scroll.
const TrackPage = () => {
const handleMenuCollapse = (e) => {
e.preventDefault();
setColapse(!colapse);
};
return (
<>
<div>
<div
className={`flex w-24 h-96 absolute top-[calc((100vh-384px)/2)] ${
colapse ? "-right-24" : "right-0"
} " bg-primary rounded-b-lg items-center justify-center`}
>
<div
className="flex w-12 h-12 absolute -top-0 -left-12 cursor-pointer bg-primary rounded-l-lg items-center justify-center"
onClick={handleMenuCollapse}
>
<SettingIcon />
</div>
Setting
</div>
</div>
</>
);
};
export default TrackPage;
App.jsx
import React, { useState, useEffect } from "react";
import Header from "./components/header";
import SideMenu from "./components/side_menu";
import AppRoutes from "./routes";
import withUser from "./hocs/with_user";
import { isMobile } from "react-device-detect";
import { useLocation } from "react-router-dom";
import { AuthProvider, setAccessToken } from
"./auth/auth_provider";
import { Toaster } from "react-hot-toast";
import AppContext from "./components/app_context";
import "./i18n";
import "./App.css";
function App(props) {
const [colapse, setColapse] = useState(isMobile);
const [sideBarFull] = useState(true);
const location = useLocation();
const IsNormalPage = () => {
const blankPages = ["/login"];
for (let i = 0; i < blankPages.length; i++) {
if (location.pathname.startsWith(blankPages[i])) return
false;
}
return true;
};
useEffect(() => {
if (props.user) setAccessToken(props.user.t);
}, []);
const PageHeader = () => {
return (
<div className="h-[72px] w-full flex items-center align-middle justify-center bg-neutral shadow">
<div className="w-full text-center">
<Header />
</div>
</div>
);
};
return (
<AuthProvider user={props.user}>
<AppContext.Provider
value={{
colapse: colapse,
setColapse: setColapse,
}}
>
<div className="relative w-full min-h-screen h-full">
<div className="flex flex-row min-h-screen">
<div className="w-auto z-0 ">
<div className="flex-1 w-full max-h-screen mx-auto text-lg h-full shadow-lg bg-white overflow-y-auto">
{IsNormalPage() && <SideMenu showFullMenu={sideBarFull} />}
</div>
</div>
<div className="w-full max-h-screen flex flex-col z-10">
{IsNormalPage() && <PageHeader />}
<div className="flex-1 w-full max-h-screen mx-auto text-lg h-full shadow-lg bg-white overflow-y-auto">
<Toaster />
<AppRoutes />
</div>
</div>
</div>
</div>
</AppContext.Provider>
</AuthProvider>
);
}
export default withUser(App);
I figured out a solution for this
First let's divide this section into two sections (the settings icon and the bigger div that you want to hide)
Then add this to the big div className: ${colapse ? "hidden" : "right-0"} so it will just be hidden instead of -right-24
and for the icon div add this to its className:${colapse ? "animate-pulse right-0": "right-24"} the animation is of course optional I just added it.
This is the code but I forgot and named the component Side.jsx instead of TrackPage.jsx
import React, { useState } from "react";
function Side() {
const [colapse, setColapse] = useState(true);
const handleMenuCollapse = (e) => {
e.preventDefault();
setColapse(!colapse);
};
return (
<div>
{/** the big div */}
<div
className={`flex w-24 h-96 bg-indigo-500 absolute top-[calc((100vh-384px)/2)] ${
colapse ? "hidden" : "right-0"
} " bg-primary rounded-b-lg items-center justify-center`}
>
Setting
</div>
{/** the icon div */}
<div
className={`flex w-12 absolute top-[calc((100vh-384px)/2)] h-12 bg-indigo-500
${colapse ? "animate-pulse right-0" : "right-24"}
cursor-pointer bg-primary rounded-l-lg items-center justify-center`}
onClick={handleMenuCollapse}
>
<div className="w-5 h-5 bg-white rounded-full " />
</div>
</div>
);
}
export default Side;
take a look Live on codesandbox.
Related
import React from "react";
import { pricing } from "../../database";
import { Fade, Zoom } from "react-reveal";
import { PricingCard } from "../Pricing";
const Pricing = () => {
const { email } = pricing;
return (
<div className="flex items-center justify-center mt-40 flex-col dark:text-white">
<Zoom left cascade>
<h1 className="font-bold text-4xl my-3">PRICING</h1>
</Zoom>
<Zoom>
<h2>I will work according to your choice</h2>
</Zoom>
<div className="flex justify-center gap-10 bg-opacity-50 dark:text-white leading-loose ">
<PricingCard />
</div>
</div>
);
};
export default Pricing;
I want Zoom style work in desktop version only and disable on mobile version, I'am using react js and tailwindCSS, hope my react-reveal can use with them
You can use with just css tricky ) Now zoom is working only large (lg) devices
import React from "react";
import { pricing } from "../../database";
import { Fade, Zoom } from "react-reveal";
import { PricingCard } from "../Pricing";
const Pricing = () => {
const { email } = pricing;
return (
<div className="flex items-center justify-center mt-40 flex-col dark:text-white">
<div className="hidden lg:block">
<Zoom left cascade>
<h1 className="font-bold text-4xl my-3">PRICING</h1>
</Zoom>
<Zoom>
<h2>I will work according to your choice</h2>
</Zoom>
</div>
<div className="lg:hidden">
<h1 className="font-bold text-4xl my-3">PRICING</h1>
<h2>I will work according to your choice</h2>
</div>
<div className="flex justify-center gap-10 bg-opacity-50 dark:text-white leading-loose ">
<PricingCard />
</div>
</div>
);
};
export default Pricing;
Hello I am developing a page to search for gifs and I get the error when I search for a larger amount of gifs than I asked for the first time, for example if I ask for 15 gisf and then another 15 different gifs I get no error but if I ask for 15 and then 30 the error appears.
The gif grid component:
`
function Gifs(props: any) {
return (
<div className="gifs-container grid grid-cols-1 md:grid-cols-4 gap-5 ">
{props.gifList.map((gif: gif, index: number) => {
const [active, setActive] = useState(false);
return (
//img container
<div
className="gif-box w-[200px] h-[150px] relative text-white"
key={index}
>
{/* Image */}
<img
src={gif.url}
alt={gif.title}
className="w-full h-full object-cover"
/>
{/* Image overlay */}
<div
className="img-overlay absolute w-full h-full opacity-0 top-0 flex flex-col
items-center bg-[rgba(0,0,0,0.6)] transition duration-100 hover:opacity-100
justify-around overflow-hidden"
>
{/* Overlay Tittle */}
<div className="overlay-tittle font-bold text-xl text-center w-[80%]">
{notGif(gif.title)}
</div>
{/* Overlay Buttons */}
<div className="overlay-buttons grid-cols-2 w-[40%] flex justify-between items-center">
<button
className="viewLink w-8 h-8 hover:opacity-60"
onClick={() => {
window.open(gif.url, "_blank");
}}
></button>
<div className={`copyMessage ${active ? "active" : ""}`}>
<button
className="copyLink w-9 h-9 hover:opacity-60"
onClick={() => {
navigator.clipboard.writeText(gif.url);
setActive(true);
setTimeout(() => {
setActive(false);
}, 500);
}}
></button>
</div>
</div>
</div>
</div>
);
})}
</div>
);
}
export default Gifs;
the app component:
function App() {
const [gifList, setGifList] = useState<gif[]>([]);
const [gifCuantity, setGifCuantity] = useState("Cantidad");
const [gifName, setGifName] = useState("");
const setGifCuantityF = (newGifCuantity: string) => {
setGifCuantity(newGifCuantity);
};
const setGifNameF = (newGifName: string) => {
setGifName(newGifName);
};
const setGifListFun = (newGifList: gif[]) => {
setGifList(newGifList);
};
useEffect(() => {
if (gifCuantity !== "Cantidad" && gifName !== "") {
getGfifs(gifName, gifCuantity, setGifListFun);
setGifCuantity("Cantidad");
}
}, [gifName]);
return (
<div className="App">
<div className="h-screen ">
<div className="mx-auto flex flex-col justify-center items-center gap-8">
<Title />
<Browser
gifCuantity={gifCuantity}
setGifCuantityF={setGifCuantityF}
setGifNameF={setGifNameF}
/>
{/* <Cgifs gifList={gifList} /> */}
<Gifs gifList={gifList} />
</div>
</div>
</div>
);
}
`
i think the main proble is on the gifList useState, this is the useState that will contain all the gifs i fetch, so if the useState had array had 15 boxes and then i fetch for 20 gifs the error will say that the 5 new boxes were null before an now they are a useState
I'm currently building a next.js app and I've run into an issue with Firebase (v8) Authentication where eventhough I can login, (and it works) I can't access the logged in user in my header since the the property of the user image is apparently undefinedeventhough on the console it appears!
import Image from "next/image";
import { MenuIcon, UserCircleIcon, SearchIcon, UsersIcon } from '#heroicons/react/solid';
import { useState } from "react"
import 'react-date-range/dist/styles.css'; // main style file
import 'react-date-range/dist/theme/default.css'; // theme css file
import { DateRange } from 'react-date-range';
import { useRouter } from "next/router";
import firebase from "../firebase/clientApp";
import { useAuthState } from 'react-firebase-hooks/auth'
function Header({ placeholder }) {
const [searchInput, setSearchInput] = useState("");
const [startDate, setStartDate] = useState(new Date());
const [endDate, setEndDate] = useState(new Date());
const [noOfGuests, setNoOfGuests] = useState(1);
const router = useRouter();
return(
<header className='sticky top-0 z-50 grid grid-cols-3 bg-white shadow-md p-5 md:px-10'>
{/* left */}
<div className='relative flex items-center h-10 cursor-pointer my-auto'>
</div>
{/* middle - search */}
<div className='flex items-center mb:border-2 rounded-full py-2 md:shadow-sm'>
<input
value = {searchInput}
className='flex-grow pl-5 bg-transparent outline-none text-sm text-gray-600 placeholder-gray-400'
type="text"
/>
<SearchIcon
className='hidden md:inline-flex h-8 bg-blue-800 text-white rounded-full p-2 cursor-pointer md:mx-2'
/>
</div>
{/* right */}
<div className='flex items-center space-x-4 justify-end text-gray-500'>
<p className='hidden md:inline cursor-pointer'>Become a host</p>
<div className='flex items-center space-x-2 border-2 p-2 rounded-full cursor-pointer'>
<div className="flex items-center space-x-2" onClick={() => router.push("/login")}>
<MenuIcon className='h-6'/>
{/* Icon change - Here is where the code kabooms */}
{firebase.auth().currentUser !== null ?
(<Image className="h-6" src={firebase.auth().photoURL} width="100%" height="100%" objectFit="cover"/>):(<UserCircleIcon className='h-6'/>)}
</div>
</div>
</div>
</header>
);
}
export default Header
You would find photoURL property inside currentUser.
Change <Image className="h-6" src={firebase.auth().photoURL} width="100%" height="100%" objectFit="cover"/> to (<Image className="h-6" src={firebase.auth().currentUser.photoURL} width="100%" height="100%" objectFit="cover"/>
So I'm making this app and I need to fade in the menu when I click the button. I have it rendering on click using state, but I can't get it to fade in / fade out on click. When I edit the opacity value inside Chrome Dev Console the transition works fine, but when I want to change it using state it doesn't.
Any help? Thanks in advance!
import React, { useState } from "react";
import { useRouter } from "next/router";
import { MenuIcon, XIcon } from "#heroicons/react/outline";
function Header() {
const router = useRouter();
const [popCard, setPopCard] = useState("hidden");
const [fade, setFade] = useState(true);
const handleMenuClick = () => {
setPopCard("inline-block");
setFade(true);
};
const handleXClick = () => {
setPopCard("hidden");
setFade(false);
};
return (
<div className="text-center">
<header className="sticky z-50 top-0 shadow-md bg-white border-b p-5">
<div className="flex justify-between items-center">
<h1
className="text-6xl text-red-500 cursor-pointer"
onClick={() => router.push("/")}
>
Velvet
</h1>
<MenuIcon
className="h-8 text-red-500 cursor-pointer"
onClick={handleMenuClick}
/>
</div>
</header>
<div
className={
popCard +
" w-[60%] flex-col border my-10 pb-3 rounded-3xl shadow-lg transition duration-300 ease-in-out " +
`${fade === true ? "opacity-100" : "opacity-0"}`
}
>
<div className="flex justify-end">
<XIcon
className="h-6 text-red-500 cursor-pointer mt-2 mr-2 opacity-70"
onClick={handleXClick}
/>
</div>
<div className="space-y-8 text-3xl text-center mt-5 mb-10 text-red-500">
<h1>Contac</h1>
<h1>About Us</h1>
</div>
</div>
</div>
);
}
export default Header;
codesandbox: Sandbox
Just to be clear, I want the menu card to fade in when I click the menu button, and I want the menu card to fade out when I click the close button.
The solution is, you need to add duration, like this:
`transition-all duration-200 ${fade ? "opacity-100" : "opacity-0"}`
Here is my forked sandbox you had given, I've removed extra inline CSS, so it may become evident.
Here is the complete code:
function Header() {
const [popCard, setPopCard] = useState("hidden");
const [fade, setFade] = useState(false);
const handleMenuClick = () => {
setPopCard("inline-block");
setFade(true);
};
const handleXClick = () => {
setPopCard("hidden");
setFade(false);
};
console.log(fade, "fade");
return (
<div className="text-center">
<header className="sticky z-50 top-0 shadow-md bg-white border-b p-5">
<div className="flex justify-between items-center">
<h1 className="text-6xl text-red-500 cursor-pointer">Velvet</h1>
<button
className="text-3xl border rounded-lg px-5"
onClick={handleMenuClick}
>
Menu
</button>
</div>
</header>
<div className="p-10">
<div
className={`transition-all duration-200 ${
fade ? "opacity-100" : "opacity-0"
}`}
>
<div className="flex justify-end">
<button className="mt-2 mr-2 border p-2" onClick={handleXClick}>
Close
</button>
</div>
<div className="space-y-2 text-3xl text-center mt-5 mb-10 mx-5 text-red-500">
<h1>Kontakt</h1>
<h1>O Velvetu</h1>
</div>
</div>
</div>
</div>
);
}
export default Header;
Sandbox: https://codesandbox.io/s/sweet-swartz-mr3nru?file=/pages/index.js:41-1396
I'm building a NextJs web app where the user can explore various stores near him.
I'm using google places Api to select location from the places dropdown.
Based on the location the stores are displayed.
Rather typing the location I want a buttons with city name which on click will set the location of that city.
Here search bar and get current location button is present along with
city button
Location.tsx
useEffect(()=>{
if(!getLocation?.formattedAddress){
setLocation(true);
setHasLoction(false);
}else{
setHasLoction(true);
}
},[])
function changeLocation(data:any){
var location=JSON.stringify(data);
console.log(data?.formattedAddress);
document.getElementById("location_id").value=data?.formattedAddress;
setLocation(data?.formattedAddress);
if(location){
setHasLoction(true);
// closeLocation();
}
var {query ,pathname} = router;
var pathname="/"+router.locale+pathname
router.push(
{
pathname,
query: query,
},
{
pathname,
query: query,
},
);
handleLocation()
}
return (
<div style={{zIndex: 1000}} className={`absolute flex flex-col w-full z-1000 inset-0 shadow-lg transform ml-0 duration-200 ease-in
${location ? ' translate-y-0 ' : '-translate-y-full' } transform border-5 bg-gray-100 h-screen lg:h-100 xl:h-110 2xl:h-110 overflow-y-hidden overflow-hidden `}>
<div className='border-red-400 flex w-full'>
<div className='flex flex-col'>
<h4 className='block lg:hidden text-sm sm:text-2xl md:text-3xl lg:text-4xl mx-4 sm:mx-16 md:mx-16 mt-8 text-magenta font-heading font-semibold'>
</h4>
<div className=''>
<p className=' lg:hidden flex mx-4 sm:mx-16 md:mx-16 mt-4 font-semibold items-center text-xs
xs+:text-sm sm:text-sm text-gray-700'>
Local stores </p>
<p className=' lg:hidden flex mx-4 sm:mx-16 md:mx-16 mt-0 font-semibold items-center text-xs
xs+:text-sm sm:text-sm text-gray-700'>
</p>
</div>
</div>
<img src='/drop-down.jpg' className='hidden lg:block md:relative object-fill md:object-contain'/>
</div>
{/* <HeaderMiddle/> */}
<div className='flex items-center justify-between mx-auto mt-20 '>
{/* <Logo className="mx-auto" /> */}
<img src="/icons/x.svg" onClick = {closeLocation}
style={{zIndex: 100}} className={`${(hasLocation)?"":"hidden"} absolute font-bold z-40 h-7 w-7 top-2 bg-gold rounded-full right-2 2xl:top-5 text-gray-400 2xl:h-8 2xl:w-8 2xl:right-7 `}/>
{/* <h2 className=' font-md text-md sm:text-lg md:text-lg lg:text-lg 2xl:text-2xl '> Get best deals in your name </h2> */}
</div>
{/* <img src='/drop-down.jpg' className='relative top-0 object-contain'/> */}
<div id='location-input' style={{zIndex: 0}}
className='absolute flex flex-col justify-center
w-full lg:w-full items-center pt-36 sm:pt-20 md:pt-4 lg:pt-0 space-y-6 ml-0 mx-3
sm:mx-16 md:ml-16 lg:ml-6 xl:ml-8 2xl:ml-10 lg:mt-80'>
<div style = {{zIndex: 1000}}
className='w-full'>
<GooglePlacesAutocomplete onChange = {changeLocation}
address =
{getLocation?.formattedAddress} />
</div>
<div style={{zIndex: 1000}} className='w-full'>
<GetCurrentLocation onChange = {changeLocation} />
</div>
</div>
<div className='-mt-10'>
<button onClick={setCityLocation}
className='p-2 border'>
New York
</button>
</div>
{/* <Dialog.Overlay className="fixed inset-0 bg-gray-900 bg-
opaname-80 w-full h-full" /> */}
</div>
google-places-autocomplete.tsx
import { Autocomplete, useJsApiLoader } from "#react-google-maps/api";
import { Libraries } from "#react-google-maps/api/dist/utils/make-load-script-url";
import { LocationInput } from "#ts-types/generated";
import React, { useState ,useEffect } from "react";
import { useTranslation } from "next-i18next";
import Loader from "#components/ui/loader/loader";
import { useLocation } from "#contexts/location/location.context";
import { useCreateLogMutation } from "#data/log/use-create-log.mutation";
import useOnClickOutside from "#utils/use-click-outside";
const libraries: Libraries = ["places"];
// data,
// data: LocationInput;
export default function GooglePlacesAutocomplete({address,
onChange
}: {
onChange: any;
address :any
}) {
const { t } = useTranslation();
const [loc,setLocation]=useState(address);
const { mutate: createLog, isLoading: loading } = useCreateLogMutation();
const { isLoaded, loadError } = useJsApiLoader({
id: "google_map_autocomplete",
googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAP_API_KEY!,
libraries,
});
const [autocomplete, setAutocomplete] = React.useState<any>(null);
const onLoad = React.useCallback(function callback(autocompleteInstance) {
setAutocomplete(autocompleteInstance);
}, []);
const onUnmount = React.useCallback(function callback() {
setAutocomplete(null);
}, []);
const onPlaceChanged = () => {
const place = autocomplete.getPlace();
if (!place.geometry || !place.geometry.location) {
console.log("Returned place contains no geometry");
return;
}
setLocation(place.formatted_address);
const location: any = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
formattedAddress: place.formatted_address,
};
for (const component of place.address_components) {
// #ts-ignore remove once typings fixed
const componentType = component.types[0];
switch (componentType) {
case "postal_code": {
location["zip"] = component.long_name;
break;
}
case "postal_code_suffix": {
location["zip"] = `${location?.zip}-${component.long_name}`;
break;
}
case "locality":
location["city"] = component.long_name;
break;
case "administrative_area_level_1": {
location["state"] = component.short_name;
break;
}
case "country":
location["country"] = component.long_name;
break;
}
}
if (onChange) {
onChange(location);
createLog({location:location.formattedAddress}, {
onSuccess: (data: any) => {
console.log(data)
},
onError: (error: any) => {
},
});
}
};
if (loadError) {
return <div>{t("common:text-map-cant-load")}</div>;
}
return isLoaded ? (
<Autocomplete
onLoad={onLoad}
onPlaceChanged={onPlaceChanged}
onUnmount={onUnmount}
fields={["address_components", "geometry.location", "formatted_address"]}
types={["address"]}
className="flex"
>
<input
type = "text"
defaultValue={loc}
style={{borderRadius:"5px"}}
className="p-3 pl-8 mx-8 w-full sm:px-8 sm:w-full sm:mx-auto xmd:mx-4 md:w-
full md:mx-auto
2xl:p-3 lg:p-3 lg:mx-auto lg:w-full 2xl:w-full 2xl:mx-auto font-
light
focus:border-accent focus:bg-light bg-gray-80
outline-none text-xs sm:text-sm md:text-base lg:text-lg
border-gray-300 border "
/>
</Autocomplete >
) : (
<div className="flex">
<Loader simple={true} className="w-6 h-6" />
</div>
);
}