A dropdown field make the conatiner "scrollable" and cuts off the dropdown selections, selector must float above the container.
for other reasons I cannot change the overflow: auto in the outer container
Thanks for helping me
import "./styles.css";
import { useState, useRef, useEffect } from "react";
import styled from "styled-components";
export default function App() {
const ref = useRef(null);
const difference = useRef();
const [expanded, setExpanded] = useState(false);
useEffect(() => {
const height = ref.current.offsetHeight;
difference.current = height;
console.log(height);
}, [expanded]);
return (
<div
style={{ height: "60px", backgroundColor: "lightblue", overflow: "auto" }}
>
<div ref={ref} style={{ position: "relative" }}>
<span onClick={() => setExpanded((previousState) => !previousState)}>
See Options
</span>
{expanded && (
<div>
<div>
{["Option 1", "Option 2", "Option 3"].map((option, i) => (
<div
style={{
border: "1px solid green",
width: "60px"
}}
key={i}
onClick={(e) => {
e.stopPropagation();
console.log(option);
}}
>
{option}
</div>
))}
</div>
</div>
)}
</div>
</div>
);
}
Make your dropdown container have an absolute position, relative to the container it's in.
Absolute position means your parent container will ignore the width and height of the dropdown, which means the dropdown will not affect the height of the parent container.
Related
I am using Next.js and Material UI for a project.
My issue is that When Im using Material UI grid it doesn't stretch to its parent full Height.
Here is my index.tsx code:
import Head from 'next/head'
import styles from '../styles/Home.module.css'
import { useState } from 'react'
import Login from './login'
export default function Home() {
const [isConnected, setIsConnected] = useState(false)
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main style={{height: "100%", backgroundColor: "red"}}>
{isConnected? "AAA" : <Login/>}
</main>
</>
)
}
Here is my Login page code:
import { useState } from 'react';
import Box from '#mui/material/Box';
import Button from '#mui/material/Button';
import TextField from '#mui/material/TextField';
import styles from '../styles/Login.module.css'
import { Grid } from '#mui/material';
import { height } from '#mui/system';
interface LoginPageProps {
// Props go here
}
interface LoginPageState {
username: string;
password: string;
}
const LoginPage: React.FC<LoginPageProps> = (props: LoginPageProps) => {
const [state, setState] = useState<LoginPageState>({
username: '',
password: '',
});
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
if (name === 'username') {
setState({ ...state, username: value });
} else if (name === 'password') {
setState({ ...state, password: value });
}
};
const handleSignup = () => {
// Handle signup here
};
const handleSignin = () => {
// Handle signin here
};
return (
<Grid container
direction="row"
justifyContent="center"
alignItems="stretch" xs={12} sm={12} md={12}
style={{
backgroundColor: "green"
}}
>
<Grid item md={6}
direction="column"
>
<Grid item xs={12} sm={12} md={12}>
<Box
className="form"
component="form"
sx={{
height: "100%",
}}
>
<div
>
<TextField
label="Username"
variant="outlined"
name="username"
value={state.username}
onChange={handleChange}
fullWidth
/>
<TextField
label="Password"
variant="outlined"
type="password"
name="password"
value={state.password}
onChange={handleChange}
fullWidth
margin="normal"
/>
<div />
<Button className="signup" variant="contained" color="primary" onClick={handleSignup}>
Sign Up
</Button>
<Button className="signin" variant="contained" color="secondary" onClick={handleSignin}>
Sign In
</Button>
</div>
</Box>
</Grid>
</Grid>
<Grid item xs={6} sm={6} md={6}>
design
</Grid>
</Grid>
);
};
export default LoginPage;
Here is my global.css file and its the only styling not applied inline:
html, body, #__next {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
Im adding an img to clarify my issue.
red background is the main html tag - the parent
green background is the grid material ui component - the child
how to make the green component (the child) stretch its entire parent height?
I'm trying to rotate a chevronDown button in react.js but the button is static.
here is my code.
import React, { useState, useEffect, useRef } from 'react'
import { chevronDown } from '../assets';
import styles from '../styles';
import { useOnClickOutside } from '../utils';
const AmountIn = () => {
const [showList, setShowList] = useState(false);
return (
<div className={styles.amountContainer}>
<input
placeholder="0.0"
type="number"
value=""
disabled={false}
onChange={() => {}}
className={styles.amountInput}
/>
<div className="relative" onClick={() => setShowList((prevState) => !prevState)}>
<button className={styles.currencyButton}>
{"ETH"}
<img
src={chevronDown}
alt="chevron down"
className={'w-4 h-4 object-contain ml-2 ${showList ? 'rotate-180' : 'rotate-0'}'}
/>
</button>
</div>
</div>
)
}
export default AmountIn
I'm expecting the button to rotate when the cursor is pointed at the button.
You can do this with the CSS :hover selector using transform. In your CSS module, you would use something like this to flip a chevron around
.currencyButton {
// core styling
&:hover {
img {
transform: rotate(0.5turn);
}
}
}
To expand on that, you can animate the change using a CSS transition.
Summary:
I have this logo in my website header, I want this logo (image [1]) to change to another one (image [2]) on scrolling down, and to change back to the original logo (image [1]) when I scroll back to the top.
What i tried:
I tried to make it with EventListener and useEffect in the header page, but I'm getting this error below:
ERROR in src\layouts\Navbar\index.jsx
Line 12:3: 'listenScrollEvent' is not defined no-undef
My code:
import React, { useState } from 'react'
import { useEffect } from "react";
export default () => {
useState = {
imageSrc: '',
imageAlt: ''
}
listenScrollEvent = e => {
if (window.scrollY > 400) {
this.setState({
imageSrc: './/img/Smartlogger_logo.png',
imageAlt: 'smartlogger white logo'
})
} else {
this.setState({
imageSrc: './../../views/Home/image/smartLoggerheader_logo.png',
imageAlt: 'smartlogger colored logo'
})
}
}
useEffect(() => {
window.addEventListener('scroll', this.listenScrollEvent)
}, []);
return (
<header className='header-area header-sticky'>
<div className='container'>
<div className='row'>
<div className='col-12'>
<nav className='main-nav'>
{/* ***** Logo Start ***** */}
<a href='/#' className='logo'>
<style>{css}</style>
<img
src={this.setState}
alt='Smartlogger logo'
/>
</a>
{/* ***** Logo End ***** */}
</nav>
</div>
</div>
</div>
</header>
)
}
You need to make the following changes in your code. It should fix the issue.
Inside render() - img src replace src={this.setState} with src={this.state.imageSrc}
Inside listenScrollEvent function replace window.scrollY with event.srcElement.body.scrollY
it will look like this (I have used random images here):
listenScrollEvent = event => {
if (event.srcElement.body.scrollY > 400) {
this.setState({
imageSrc: 'https://c.tenor.com/57w9du3NrV0AAAAS/css-html.gif',
imageAlt: 'smartlogger white logo'
})
} else {
this.setState({
imageSrc: 'https://c.tenor.com/57w9du3NrV0AAAAS/css-html.gif',
imageAlt: 'smartlogger colored logo'
})
}
}
Full working code : (I have added style={{height:'200vh'}} on container div just to test it on my local. You can remove it)
import React from 'react'
import { Link } from 'react-router-dom'
export default class App extends React.Component {
state = {
imageSrc: 'https://c.tenor.com/TReUojNlZ6wAAAAi/js-javascript.gif',
imageAlt: ''
}
listenScrollEvent = event => {
if (event.srcElement.body.scrollY > 400) {
this.setState({
imageSrc: 'https://c.tenor.com/57w9du3NrV0AAAAS/css-html.gif',
imageAlt: 'smartlogger white logo'
})
} else {
this.setState({
imageSrc: 'https://c.tenor.com/57w9du3NrV0AAAAS/css-html.gif',
imageAlt: 'smartlogger colored logo'
})
}
}
componentDidMount() {
window.addEventListener('scroll', this.listenScrollEvent)
}
render() {
return (
<header className='header-area header-sticky'>
<div className='container' style={{height:"200vh"}}>
<div className='row'>
<div className='col-12'>
<nav className='main-nav'>
{/* ***** Logo Start ***** */}
<a href='/#' className='logo'>
{/* <style>{css}</style> */}
<img
src={this.state.imageSrc}
alt='Smartlogger logo'
/>
</a>
{/* ***** Logo End ***** */}
</nav>
</div>
</div>
</div>
</header>
)
}
}
Hope that's how you wanted it to work. Try running it on your local and then you can modify it as per your requiremnets.
In your useState hook you want to have your src and your alt.
Remember useState return an array of 2 elements, the first is the value and the second is the setter for that value.
You can use the setter in your listenScrollEvent function and you can use the value in your jsx.
You are also using a css variable in you jsx that isn't defined anywhere.
It should look something like this:
import React, { useState, useEffect } from "react";
export default () => {
const [image, setImage] = useState({
src: "",
alt: "",
});
const listenScrollEvent = (e) => {
if (window.scrollY > 400) {
setImage({
src: "../img/Smartlogger_white_logo.png",
alt: "smartlogger white logo",
});
} else {
setImage({
src: "../img/Smartlogger_colored_logo.png",
alt: "smartlogger colored logo",
});
}
};
useEffect(() => {
window.addEventListener("scroll", listenScrollEvent);
}, []);
return (
<header className="header-area header-sticky">
<div className="container">
<div className="row">
<div className="col-12">
<nav className="main-nav">
{/* ***** Logo Start ***** */}
<a href="/#" className="logo">
<style>{css}</style>
<img src={require(image.src)} alt={image.alt} />
</a>
{/* ***** Logo End ***** */}
</nav>
</div>
</div>
</div>
</header>
);
};
An alternative solution that looks a little cleaner to me:
import React, { useState, useEffect } from "react";
import whiteLogo from "../img/Smartlogger_white_logo.png";
import coloredLogo from "../img/Smartlogger_colored_logo.png";
export default () => {
const [isScrolled, setIsScrolled] = useState(false);
const listenScrollEvent = (e) => setIsScrolled(window.scrollY > 400);
useEffect(() => {
window.addEventListener("scroll", listenScrollEvent);
}, []);
return (
<header className="header-area header-sticky">
<div className="container">
<div className="row">
<div className="col-12">
<nav className="main-nav">
{/* ***** Logo Start ***** */}
<a href="/#" className="logo">
<style>{css}</style>
<img
src={isScrolled ? whiteLogo : coloredLogo}
alt={
isScrolled
? "SmartLogger white logo"
: "SmartLogger colored logo"
}
/>
</a>
{/* ***** Logo End ***** */}
</nav>
</div>
</div>
</div>
</header>
);
};
EDIT: added note about css variable, fixed typo in code and formatted better
EDIT2: fixed image link and added the require in the img src attribute, this should fix the image loading
EDIT3: added alternative solution
Header Component
<Header
className="site-layout-header"
style={{
position: "sticky",
top: 0,
zIndex: 999,
width: "100%",
padding: 30,
backgroundColor: "#fff",
...style,
}}
>
{children}
</Header>
Below this I am using header component like this
const IncidentProfile = (props: any) => {
const { record } = props.location?.state || {};
return (
<>
<Header record={record} />
<Content
className="site-layout-background"
style={{
padding: 24,
}}
>
<h1>Incident Profile Page {record?.name}</h1>
</Content>
</>
);
};
When the Header component height increases dynamically, it scrolls and stay sticky but the content below it is not showing.
Can anyone help ?
I need your help :) (but first, sorry for my aproximate english ...).
I would like to change the 'img src' in the 'div-img' when I pass the mouse over one of the 'a' balise ... I try onMouseOver, but i failled :(
There is an image by 'a' which replaces the one in 'div-img'
EDIT : Okay, here is the almost complete code, to really see the problem :
#observer
export default class Home extends React.Component {
static readonly language = "language";
private static readonly en = "en";
private static readonly fr = "fr";
#observable private static selectLanguage = false;
public render(): ReactElement {
if (Home.selectLanguage) {
return (
<div style={{ height: '100vh', width: '100vw', overflow: 'hidden'}}>
<MyHead />
<body style={{backgroundColor: 'rgb(51, 63, 72)'}}>
<div style={{
maxWidth: '1150px',
height: '300px',
margin: 'auto',
}}>
<div style={{ display: 'flex', maxWidth: '450px'}}>
<img style={{
maxWidth: '100%',
margin: 'auto'
}}
src='/images/***.png'/>
</div>
</div>
<div style={{
display: 'flex',
flexWrap: 'wrap',
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
zIndex: 1,
}}>
<a href="/fr/" onClick={_ => { localStorage.setItem(Home.language, Home.fr); }} >
<span className= 'shadow'>
<div style={{ margin: '0 15px', padding: '75px', backgroundColor: 'rgb(175, 39, 47)', clipPath: 'polygon(0 0, 100% 8%, 100% 92%, 0 100%)'}} >
<h2>Français</h2>
</div>
</span>
</a>
<a href="/en/" onClick={_ => {localStorage.setItem(Home.language, Home.en);}}>
<span className= 'shadow'>
<div style={{ margin: '0 15px', padding: '75px', backgroundColor: 'rgb(175, 39, 47)', clipPath: 'polygon(0 8%, 100% 0, 100% 100%, 0 92%)'}}>
<h2>English</h2>
</div>
</span>
</a>
</div>
<main style={{filter: 'blur(4px)'}}>
<component1 />
<component2 />
</main>
</body>
</div>
)
}
Thank you very much in advance !
I have made a few changes to your code, first of all, I am using mouseOnEnter instead of mouseOnHover and I have also added mouseOnLeave to reset the image(because in the question you have mentioned that you want to change the image when you pass over the (Link) tag.
My solution uses the useState react hook, onMouseEnter for the div sets a random image using
https://i.picsum.photos/id/${Math.floor(Math.random() * 1084)}/50/50.jpg
https://i.picsum.photos/id/{image_id}/{width}/{height}.jpg
https://i.picsum.photos/id/50/50/50.jpg
OnMouseEnter the state is updated to the images src / location and is reset to '' onMouseLeave. Also, I have added
style={{ width: '50px', height: '50px' }}
to the div so as to keep the divs from moving around when hovering over links in the sample code. 50px is also the height of the image.
import React, { useState } from 'react'
const testCode = () => {
const [image, setImage] = useState('')
return (
<>
<div className="div-img" style={{ width: '50px', height: '50px' }}>
<img src={image} />
</div>
<div>
<a href="/fr/" onMouseEnter={() => setImage(`https://i.picsum.photos/id/${Math.floor(Math.random() * 1084)}/50/50.jpg`)} onMouseLeave={() => setImage('')}>
<span className="shadow">
<div>
<h2>Lorem</h2>
</div>
</span>
</a>
<a href="/en/" onMouseEnter={() => setImage(`https://i.picsum.photos/id/${Math.floor(Math.random() * 1084)}/50/50.jpg`)} onMouseLeave={() => setImage('')}>
<span className="shadow">
<div>
<h2>Lorem</h2>
</div>
</span>
</a>
</div>
</>
)
}
export default testCode
Updated: Using React Class
import React, { Component } from 'react'
class sampleCode extends Component {
constructor(props) {
super(props);
this.state = { image: '' };
}
setImage = (imagePath) => {
this.setState({ image : imagePath })
}
render() {
return (
<>
<div className="div-img" style={{ width: '50px', height: '50px' }}>
<img src={this.state.image}/>
</div>
<div>
<a href="/fr/"
onMouseEnter={() => this.setImage(`https://i.picsum.photos/id/${Math.floor(Math.random() * 1084)}/50/50.jpg`)}
onMouseLeave={() => this.setImage('')}>
<span className="shadow">
<div>
<h2>Lorem</h2>
</div>
</span>
</a>
<a href="/en/"
onMouseEnter={() => this.setImage(`https://i.picsum.photos/id/${Math.floor(Math.random() * 1084)}/50/50.jpg`)}
onMouseLeave={() => this.setImage('')}>
<span className="shadow">
<div>
<h2>Lorem</h2>
</div>
</span>
</a>
</div>
</>
)
}
}
export default sampleCode
Hope this helps :)