enter image description here
I want to implement the above screenshot. When I click on the country dropdown, the default country name above plus the flag changes .
So far I have I have been using headless UI. The problem is that I dont know how to implement the logic in menu-item to change the default country and flag when dropdown is clicked, also the selectedactive country should be checked .Below is my code ,someone help`
import { Fragment, useState, useMemo, useEffect } from "react";
import Sidebar from "./sidebar";
import Image from "next/image";
import Link from "next/link";
import { Menu, Transition ,RadioGroup} from "#headlessui/react";
import { ChevronDownIcon } from "#heroicons/react/20/solid";
import { signOut, useSession } from "next-auth/react";
function classNames(...classes: any[]) {
return classes.filter(Boolean).join(" ");
}
const logout = () => {
signOut();
};
const LayoutContent = ({
children,
sidebar,
}: {
children: any;
sidebar: any;
}) => {
const { data: Session } = useSession();
const [active,setActive] = useState(' ')
return (
<>
<main
className={`max-w-screen-3xl mx-auto flex flex-col ${
sidebar ? "lg:pl-20" : "lg:pl-80"
}`}
>
<div className="pl-0 lg:mx-1">
<nav className="mx-1 lg:mx-1 relative w-full flex flex-wrap items-center justify-end py-1 text-gray-800 ">
<Menu as="div" className="relative inline-block text-left mr-5">
<div>
<Menu.Button className="inline-flex w-full items-center bg-white px-4 py-2 text-sm font-medium text-gray-700 ">
<Image
width={35}
height={35}
className="px-8 py-2.5"
src="/KE.svg"
alt="actions"
/>
<span className="ml-4 text-gray-700 text-[13px]">Kenya</span>
<ChevronDownIcon
className="-mr-1 ml-2 h-7 w-7"
aria-hidden="true"
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-10 mt-2 w-56 h-48 bg-white origin-top-right rounded-lg shadow-[0px_0px_28px_rgba(0,0,0,0.08)] ring-opacity-5 focus:outline-none">
<div className="py-1">
<span className="text-gray-500 ml-4 ">
Select Country
</span>
<Menu.Item>
{({ active}) => (
<a
href="#"
className={classNames(
active
? " flex items-center text-gray bg-[#FDE6D4] rounded mb-3 ml-4 mr-4 mt-2"
: "flex items-center text-gray-500 bg-gray-100 rounded mb-3 ml-4 mr-4 mt-2 ",
"block px-4 py-2 text-sm"
)}
>
<Image
width={25}
height={25}
className="px-8 py-2.5"
src="/KE.svg"
alt="actions"
/>
<span className="ml-4 text-[13px] ">Kenya</span>
</a>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<a
href="#"
className={classNames(
active
? " flex items-center text-gray bg-[#FDE6D4] rounded mb-3 ml-4 mr-4"
: "flex items-center text-gray-500 bg-gray-100 rounded mb-3 ml-4 mr-4 ",
"block px-4 py-2 text-sm"
)}
>
<Image
width={25}
height={25}
className="px-8 py-2.5"
src="/TZ (2).svg"
alt="actions"
/>
<span className="ml-4 text-[13px]">Tanzania</span>
</a>
)}
</Menu.Item>
<Menu.Item>
{({ active}) => (
<a
href="#"
className={classNames(
active
? " flex items-center text-gray bg-[#FDE6D4] rounded ml-4 mr-4"
: " flex items-center text-gray-500 bg-gray-100 rounded ml-4 mr-4",
"block px-4 py-2 text-sm"
)}
>
<Image
width={25}
height={25}
className="px-8 py-2.5"
src="/MZ.svg"
alt="actions"
/>
<span className="ml-4 text-[13px]">Mozambique</span>
</a>
)}
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>
<p>
<span className="px-0 py-2 text-gray-700 font-medium text-xs focus:outline-none focus:ring-0 active:shadow-lg transition duration-150 ease-in-out flex items-center">
<Image
width={25}
height={25}
className="p-2 rounded-full"
src="/rectangle.svg"
alt="Profile"
/>
</span>
</p>
<p>
<span className="px-1 py-2 text-gray-700 font-medium text-xs focus:outline-none focus:ring-0 active:shadow-lg transition duration-150 ease-in-out flex items-center">
{Session ? <p>{Session!.user!.name}</p> : "..."}
</span>
</p>
<p>
<span className="px-0 py-2 text-gray-700 font-medium text-xs focus:outline-none focus:ring-0 active:shadow-lg transition duration-150 ease-in-out flex items-center mr-12">
<Image
width={13}
height={13}
className="p-2 rounded-full"
src="/dropdown.svg"
alt="Profile"
/>
</span>
</p>
</nav>
{children}
</div>
</main>
</>
);
};
export default LayoutContent;
`
I just implement headless UI without logic for updating the country and flag.What other options do I have ?
Are you looking to show the selected country at top right, you can try something like this
//data
const countries = [
{
id: 1,
src: "/KE.svg",
label: "Kenya",
},
{
id: 1,
src: "/TZ (2).svg",
label: "Tanzania",
}
{
id: 1,
src: "/MZ.svg",
label: "Mozambique",
}
]
Inside component
// keep selected state
const [selected, setSelected] = useState();
// show selected country
{
selected ?
(
<div>
<Menu.Button className="inline-flex w-full items-center bg-white px-4 py-2 text-sm font-medium text-gray-700 ">
<Image
width={35}
height={35}
className="px-8 py-2.5"
src={selected.src}
alt="actions"
/>
<span className="ml-4 text-gray-700 text-[13px]">{selected.label}</span>
<ChevronDownIcon
className="-mr-1 ml-2 h-7 w-7"
aria-hidden="true"
/>
</Menu.Button>
</div>
) : null
}
// display list of countries and on click select the country
<Menu.Items className="absolute right-0 z-10 mt-2 w-56 h-48 bg-white origin-top-right rounded-lg shadow-[0px_0px_28px_rgba(0,0,0,0.08)] ring-opacity-5 focus:outline-none">
<div className="py-1">
<span className="text-gray-500 ml-4 ">
Select Country
</span>
{
data.map(country => {
return (
<Menu.Item key={country.id}
// if on click does not work here move to <a>
onClick={e => setSelected(country)}
>
{({ active}) => (
<a
href="#"
className={classNames(
active
? " flex items-center text-gray bg-[#FDE6D4] rounded mb-3 ml-4 mr-4 mt-2"
: "flex items-center text-gray-500 bg-gray-100 rounded mb-3 ml-4 mr-4 mt-2 ",
"block px-4 py-2 text-sm"
)}
>
<Image
width={25}
height={25}
className="px-8 py-2.5"
src={country.src}
alt="actions"
/>
<span className="ml-4 text-[13px] ">{country.label}</span>
</a>
)}
</Menu.Item>
)
});
}
</div>
</Menu.Items>
Hope it helps you to find a better solution
I'm building a social media app using React, Firebase, and Tailwindcsss.
I want to add an emoji picker to the new post input and be able to add the emojis to firebase firestore.
Code:
NowPost.jsx:
const NewPost = () => {
return (
<>
<div className="bg-white rounded border border-gray-300 px-5 py-3">
<form onSubmit={handleSubmit} className="flex justify-between gap-6">
<div className="flex items-center justify-center text-white uppercase text-xl w-10 h-10 rounded-full cursor-pointer bg-green-700">
<div>{user?.displayName.charAt(0)}</div>
</div>
<input
type="text"
value={post}
onChange={(e) => setPost(e.target.value)}
className="bg-gray-200 rounded-2xl w-8/12 py-2 px-3 focus:ring-orange-500 focus:ring-1 outline-none"
placeholder="what are you thinking about?"
/>
<div>
<button
type="submit"
className="flex items-center gap-2 transition-all duration-100 bg-orange-500 hover:bg-orange-600 rounded-lg p-3 text-white"
>
Post <IoSend />
</button>
</div>
</form>
</div>
</>
);
};
I am trying to implement a simple age verification modal in a react app that I would like to launch only once; when a user first accesses my app. However, currently the modal pops up every time the page is refreshed or a redirect to a new page is clicked and I cannot stop this from happening even though I have coded the state to be set open once the confirm button is clicked.
The code for my modal component is as follows;
import { Fragment, useRef, useState } from 'react'
import { Dialog, Transition } from '#headlessui/react'
import { ExclamationTriangleIcon } from '#heroicons/react/24/outline'
import Modal from 'react-modal';
export default function Example() {
const [open, setOpen] = useState(true)
return (
<Transition.Root show={open} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={() => null}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg">
<div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div className="sm:flex sm:items-start">
<div className="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<ExclamationTriangleIcon className="h-6 w-6 text-red-600" aria-hidden="true" />
</div>
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<Dialog.Title as="h3" className="text-xl font-medium leading-6 text-gray-900">
Age Verification
</Dialog.Title>
<div className="mt-2">
<p className="text-md text-gray-500">
You must be over 18 to enter.
</p>
</div>
</div>
</div>
</div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6">
<button
type="button"
className="inline-flex w-full justify-center rounded-md border border-transparent bg-purple-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 sm:ml-3 sm:w-auto sm:text-sm"
onClick={() => setOpen(false)}
>
Confirm
</button>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
)
}
Can help me with how I could set the state to be closed on first launch and then to open once 'confirm' is clicked and have it stay that way?
Thank you
i created responsive mobile menu with tailwind css in react js project. All code works fine. There's no error in my code. When i use in rendeaning ref it gives me a waring in console. "Unexpected ref object provided for div. Use either a ref-setter function or React.createRef()." How can i solve it?
https://i.ibb.co/PG0xFwn/Screenshot-2022-05-01-at-3-43-35-PM.png
<Transition
show={isOpen}
enter="transition ease-out duration-100 transform"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="transition ease-in duration-75 transform"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
{(ref) => (
<div className="lg:hidden" id="mobile-menu">
<div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3">
<CustomLink
to="/"
className=" hover:bg-red-700 text-white block px-3 py-2 rounded-md text-base font-medium"
>
Home
</CustomLink>
<CustomLink
to="/manage"
className="text-gray-300 hover:bg-red-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium "
>
Manage Inventories
</CustomLink>
{user && (
<>
<CustomLink
to="/addInventory"
className="text-gray-300 hover:bg-red-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium"
>
Add Item
</CustomLink>
<CustomLink
to="/myItem"
className="text-gray-300 hover:bg-red-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium"
>
My Items
</CustomLink>
</>
)}
<CustomLink
to="/blog"
className="text-gray-300 hover:bg-red-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium"
>
Blog
</CustomLink>
{user ? (
<button
onClick={logOut}
className="border-2 bg-red-700 hover:bg-indigo-700 hover:border-white-700 px-4 py-1 text-white rounded-sm transition-all duration-300 ease-in-out focus:shadow-outline focus:outline-none"
>
Logout
</button>
) : (
<button
onClick={() => navigate("/login")}
className="border-2 hover:bg-red-700 hover:border-red-700 px-4 py-1 text-white rounded-sm transition-all duration-300 ease-in-out focus:shadow-outline focus:outline-none"
>
Login
</button>
)}
</div>
</div>
)}
</Transition>
you can solve this by creating the ref variable using useRef() hook or React.createRef() and then pass the variable directly to the ref prop
const divRef = useRef()
Then you can use the ref
<div ref={divRef} > </div>
or if you are using class component
this.divRef = React.createRef()
then
<div ref={this.divRef} > </div>
trying to prevent default on form submission though it goes ahead and submits user input--
if I have the form onsubmit value to empty then the form prevents default.. is there solution to this?
Below is my form; on submit is empty as it prevents default when empty. though it should be going to generate as shown below...
<form className='grid' onSubmit={}>
<div className='flex'>
{/* <InputField
isRequired={true}
id='productNameField'
required={true}
className='border-solid border-2 border-gray-200 pl-3 w-full rounded-lg h-full'
type='text'
placeholder='Spotify'
label='Product Name'
onChange={onSetProductName}
/> */}
<div className=' relative '>
<label className='text-gray-700'>
Product Name
<span className='text-red-500 required-dot'>*</span>
</label>
<input
type='text'
required
className=' rounded-lg border-transparent flex-1 appearance-none border border-gray-400 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-accent1 focus:border-transparent'
placeholder='Spotify'
onChange={onSetProductName}
/>
</div>
</div>
{/* <div className='flex pt-6'>
<InputField
id='productDescriptionField'
required={true}
className='border-solid border-2 border-gray-200 pl-3 w-full rounded-lg resize-none h-full p-1'
type='text'
placeholder='Spotify is a music service that lets you listen to music and share it with friends.'
label='Product Description'
maxRows={5}
onChange={onSetProductDescription}
multiline
/>
</div>
<div className='flex pt-6'>
<InputField
id='platformField'
required={true}
className='border-solid border-2 border-gray-200 pl-3 w-full rounded-lg h-full'
type='text'
placeholder='Instagram'
label='Platform'
onChange={onSetPlatform}
/>
</div>
<div className='flex pt-6'>
<InputField
id='audienceField'
required={true}
className='border-solid border-2 border-gray-200 pl-3 w-full rounded-lg h-full'
type='text'
placeholder='Teens'
label='Audience'
onChange={onSetAudience}
/>
</div> */}
<div className='grid'>
<div className='grid grid-cols-2 pt-6'>
{pendingCreativeAd === true ? (
<div className='grid justify-start'>
<button
type='button'
disabled={true}
className='py-2 px-4 flex justify-center items-center bg-gray-600 text-white w-full transition ease-in duration-200 text-center text-base font-semibold rounded-lg '
>
1 sec.
<LoadingIcon height={21} width={21} />
</button>
</div>
) : (
<div className='grid justify-start'>
<button
type='submit'
// onClick={generate}
className='py-2 px-4 flex justify-center items-center bg-accent1 hover:bg-blue-800 focus:bg-accent1 text-white w-full transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none rounded-lg '
>
Generate
</button>
</div>
)}
<div className='grid justify-end'>
<button
type='button'
onClick={clearForm}
className='py-2 px-4 flex justify-center items-center bg-orange-700 hover:bg-orange-800 text-white w-full transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:bg-orange-700 rounded-lg '
>
Clear Form
</button>
</div>
</div>
</div>
</form>
const generate = async (e) => {
e.preventDefault();
startGenAd(productName, productDescription, platform, audience);
console.log('submitting generate');
};
Just use your generate function in Form's Submit Event Instead of Button's Click Event. I think this is the easiest Approach.
set type e to
const generate = async (e: { preventDefault: () => void; }) => {
e.preventDefault();
startGenAd(productName, productDescription, platform, audience);
console.log('submitting generate');
};