Hover "Drop Right" Menu - javascript

I am trying to implement a side-menu that would expand a "table" of items when you hover over one of its items. I'm using TailwindCSS and React.
The problem I'm facing is that the menu does not expand when I hover over the button.
I've made the sub-menu a child of the button so that I could use the group-hover functionality, but it does not work. I already added display: ['hover', 'focus'] to the variants config, so, that can't be the problem.
// SideMenuItem.js
import React from "react";
function SideMenuItem() {
return (
<button className="group static m-2 w-16 h-16 bg-red-400"> A
<div className="hidden group-hover:block relative top-0 left-24 w-48 z-10 flex flex-row flex-wrap bg-gray-300">
<button className="m-2 h-16 w-16 bg-gray-200">Item 1</button>
<button className="m-2 h-16 w-16 bg-gray-200">Item 2</button>
<button className="m-2 h-16 w-16 bg-gray-200">Item 3</button>
</div>
</button>
);
}
export default SideMenuItem;
Desired Output:

I have found this code sample from an article.
https://codesandbox.io/s/59574892-so-n-number-of-dropdowns-9hkt3
Try to understand what the man did and write it on your own.
Best of luck!

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>
);
}

Applying Tailwind overflow behavior to only one child element

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;

JS click event listener in laravel livewire component?

I'm trying to add some JS to add a click event to an element within a livewire component. The click event works as expected on first load, however as soon as I run a wire:click, the JS click events no longer work?
I can see that livewire is removing / updating the dom elements when I click the wire:click element so unsure whether this may have something to do with it.
What am I doing wrong? How should I be registering click events to livewire elements in JS and ensure they always work?
My javascript:
document.addEventListener('livewire:load', function () {
let pb_responsive_button = [...document.querySelectorAll('.js-pb-responsive')];
pb_responsive_button.map(function (btn) {
btn.addEventListener("click", function () {
console.log('click');
});
});
});
livewire:
<button wire:click="addComponentActive(true)">
<span class="font-bold text-sm">Add Page Block</span>
</button>
public function addComponentActive(bool $bool)
{
$this->add_component_active = $bool;
}
my view:
#if ($add_component_active === true)
<section class="bg-white shadow-lg rounded-sm mb-8 w-full h-[calc(100%-64px)] absolute z-50">
.....
</section>
#endif
<section class="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
<div class="border border-gray-200 rounded">
<div class="bg-gray-200 p-5 flex justify-between">
<div class="bg-white border border-gray-200 rounded p-2">
<span class="font-bold text-sm">Homepage</span>
</div>
<div class="bg-blue-600 text-white border border-gray-200 rounded p-2">
<button wire:click="addComponentActive(true)">
<span class="font-bold text-sm">Add Page Block</span>
</button>
</div>
<div class="flex justify-between items-center gap-2">
<div class="js-pb-responsive js-pb-mobile bg-white border border-gray-200 rounded p-2">M</div>
<div class="js-pb-responsive js-pb-tablet bg-white border border-gray-200 rounded p-2">T</div>
<div class="js-pb-responsive js-pb-desktop bg-white border border-gray-200 rounded p-2">D</div>
</div>
</div>
</div>
</section>
UPDATE:
I've updated it to show and hide the blocks rather than display it in a conditional if statement which ensures the click events still work, since the element still exists on page.
<section class="{{$add_component_active === true ? 'block' : 'hidden'}}"> ... </section>
Surely there is a better way to handle this. I notice I have a livewire:load eventListener? Is there another event I should be listening to when the livewire view is reloaded to reinitise the JS events?
Any help would be much appreciated.
Livewire works hand-in-hand with Alpine.js. You should focus on Alpine if you want strictly front-end functionality https://alpinejs.dev/directives/on
<button #click="alert('Hello World!')">Say Hi</button>

I'm trying to build a dropdown when cursor hovers on a navbar element pointing to that element with an arrow up

I am using NextJS and Tailwind CSS. I already built the dropdown but I have an issue building the arrow pointing to the specific element. I built the arrow in a previous version using a div rotated at 45deg but then I couldn't make my dropdown take the full screen. Now I have it full screen and I'm wondering how to make the arrow (div) point to the specific element I'm hovering on. I made sure to hide some details about the website because of confidentiality matters. Here's what I'm trying to achieve:
Here's the code I have so far:
import React from 'react'
import { navLinks } from '../data/navdata'
const DropdownHover = ({ index }) => {
return (
<div className="group-hover:block absolute left-0 w-full hidden text-dark-gray mt-8 bg-pink" aria-labelledby="dropdownButton">
<div className="justify-center">
<div className="flex py-10 px-20 text-sm justify-between">
{navLinks[index].hover.map((link, index) => {
return (
<div className="" key={index}>
<p className="text-navbar-gray py-2 uppercase font-semibold">{link.name}</p>
{link.links.map((sublink, index) => {
return(<p className="" key={index}><a className="bg-pink hover:text-red py-2 block whitespace-no-wrap" href={sublink.path}>{sublink.name}</a></p>)
})}
</div>
)
})}
</div>
<div className="flex text-sm px-20 py-10">
<div className='pr-40'>
<p className="text-navbar-gray py-2 uppercase font-semibold">Dummy Data</p>
<p className=""><a className="bg-pink hover:text-red py-2 block whitespace-no-wrap" href="#">Dummy Data</a></p>
<p className=""><a className="bg-pink hover:text-red py-2 block whitespace-no-wrap" href="#">Dummy Data</a></p>
<p className=""><a className="bg-pink hover:text-red py-2 block whitespace-no-wrap" href="#">Dummy Data</a></p>
</div>
<div>
<p className="text-navbar-gray py-2 uppercase font-semibold">Dummy Data</p>
<p className=""><a className="bg-pink hover:text-red py-2 block whitespace-no-wrap" href="#">Dummy Data</a></p>
<p className=""><a className="bg-pink hover:text-red py-2 block whitespace-no-wrap" href="#">Dummy Data</a></p>
<p className=""><a className="bg-pink hover:text-red py-2 block whitespace-no-wrap" href="#">Dummy Data</a></p>
</div>
</div>
</div>
</div>
)
}
export default DropdownHover
in CSS you can simply manipulate left property of the arrow if its positioned absolute:
li :nth-child(1):hover .arrow{
left:20rem;
}
li :nth-child(2):hover .arrow{
left:30rem;
}
but if you want to make it completely responsive, first get OffsetX of every li element then add an event listener on mouseclick.
for a better understanding you can check the following project on code pen.
https://codepen.io/piyushpd139/pen/gOYvZPG

open a dialogue box just like model but attached to the element

I am new to React Js, I want to open a drop down box which may contain buttons, input fields, e.t.c but the issue is that I have tried model dropdown and many solutions but that does not attach exactly to the bottom of the element opening the dropdown when it is clicked. Another problem is that the component it is contained is just max 50px height so the model should be floating over that component.
In the Image attached the box is opening when open is clicked and the upper blue strip component contain the code but its is displaying on both
just want the box that can contain elements and position exactly under the element it is opened by
import React from "react"
import UserTopBar from "./UserTopTab"
import BelowSection from "./BelowSection"
const Parent =()=>{
<UserTopBar />
<BelowSection />
}
export default Parent
//Top Bar
import React from 'react';
import Notification from '../Notification'
import { NavLink } from 'react-router-dom'
import { QuestionCircleFilled, CloseOutlined } from '#ant-design/icons';
class UserTopTab extends React.Component {
render() {
return (
<>
<div className="d-inline-flex" style={{ background: "#242F84", width: "100%", zIndex: "990" }}>
<NavLink to="/" className="Cambium ">
<p className="mb-0 px-2 White" >Title</p>
</NavLink>
<NavLink to="/AllSearches" className='tab my-auto TabStyle'>
<p className="mb-0 FS_20 px-2 White" >All Searches</p>
</NavLink>
<NavLink to="/AllSearches" className='tab my-auto TabStyle'>
<p className="mb-0 FS_20 px-2 White" >Untitled 1</p>
</NavLink>
{this is toogle button when clicked it will open a dialogue box attached to its bottom}
<button type="button" className="mb-0 FS_20 px-2 White" >Open +</button>
{*innerpart of the box*}
<Notification />
<p className="mb-0 Help"><QuestionCircleFilled /></p>
</div>
</>
);
}
}
export default UserTopTab;
//Second Section
import React from 'react';
const BelowSection =()=>{
<div>
<h1>bellow Section is displayed here </h1>
</div>
}
export default BelowSection
Replace the button that is used to open the box with the target button bellow you can do any thing inside the dialogue box that is opened
<div class="dropdown newTab">
<button type="button"
className="mb-0 FS_20 px-2 White Grey border-0 h-100 dropdown-toggle"
id="dropdownMenuButton" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false"
style={{ backgroundColor: "#050A30" }} >Open +</button> //target from where you want to place the buton
<div class="dropdown-menu p-0" aria-labelledby="dropdownMenuButton">
Your inner code to be in here that you
need to display in the Drop down Box
</div>
</div>

Categories

Resources