I have a problem where the mouse does not follow the div closely due to parent div left and top. Assume parent.jsx is developed by another developer, and I solely can control child.jsx, is there a way for me to make the div follow the mouse?
Here's the parent jsx
import "./styles.css";
import Child from "./child";
export default function Parent() {
return (
<div
style={{
top: "25px",
left: "20px",
position: "relative"
}}
>
<Child />
</div>
);
}
The child jsx
import "./styles.css";
import { useRef } from "react";
export default function Child() {
const descBox = useRef(null);
const handleMove = (e) => {
console.log(e.clientX, e.clientY);
descBox.current.style.left = `${e.clientX}px`;
descBox.current.style.top = `${e.clientY}px`;
};
return (
<>
<div
onMouseMove={handleMove}
style={{
height: "300px",
width: "100%",
backgroundColor: "red"
}}
></div>
<div className="dropdown1" ref={descBox}>
123asdfsfdafffasdfasfdsajkj
</div>
</>
);
}
The css for child
.dropdown1 {
position: absolute;
left: 150px;
top: 10px;
background: #2b4557;
padding: 4px 8px;
font-size: 12px;
line-height: 18px;
color: #fff;
}
Codesandbox to run the code.
As the child is positioned absolute within the relative positioned parent you can work out its left and top positions relative to the parent and use those.
This code adds a small offset to give a slight gap between the cursor and the child (which you may or may not want).
const handleMove = (e) => {
const rect = e.target.getBoundingClientRect();
const x = e.clientX - rect.left + 10;
const y = e.clientY - rect.top + 10;
descBox.current.style.left = `${x}px`;
descBox.current.style.top = `${y}px`;
};
Related
I am new into Grafana. I created a custom plugin on which I have a Button. The project compiles without issues, and the button appears on the panel, but no click event is handled
Please find below the source code
import React from ‘react’;
import { PanelProps } from ‘#grafana/data’;
import { SimpleOptions } from ‘types’;
import { css, cx } from ‘#emotion/css’;
import { Button, useStyles2, useTheme2 } from ‘#grafana/ui’;
interface Props extends PanelProps {}
const getStyles = () => {
return {
wrapper: css font-family: Open Sans; position: relative; ,
svg: css position: absolute; top: 0; left: 0; ,
textBox: css position: absolute; bottom: 0; left: 0; padding: 10px; ,
hover:css background-color: rgba(255, 0, 0, 1); ,
active:css background-color: rgba(255, 255, 0, 1); ,
};
};
export const SimplePanel: React.FC = ({ options, data, width, height }) => {
const theme = useTheme2();
const styles = useStyles2(getStyles);
return (
<div
className={cx(
styles.wrapper,
css width: ${width}px; height: ${height}px;
)}
>
<svg
className={styles.svg}
width={width}
height={height}
xmlns=“SVG namespace”
xmlnsXlink=“XLink namespace”
viewBox={-${width / 2} -${height / 2} ${width} ${height}}
>
<circle style={{ fill: theme.colors.primary.main }} r={100} />
<div className={styles.textBox}>
{options.showSeriesCount && <div>Number of series: {data.series.length}</div>}
<div>Text option value: {options.text}</div>
</div>
<Button onClick={()=>console.log("test")}>TestButton</Button>
</div>
);
};
I also changed in the defaults.ini the disable_sanitize_html = true but the problem didn’t get solved.
Please can you advice what to do next.
I set the disable_sanitize_html=true but didn't work.
I am trying to build a react component with a large fixed div and a navbar below. Initially, the div should remain fixed at the top left and scroll through a number of slides as the user scrolls, before its display property reverts to absolute and it scrolls out of view. Meanwhile, the nav's position becomes sticky and scrolls to the top of the window where it remains.
I've managed to build something hacky using react-intersection-observer and a number of hidden 'ghost' elements which allow the slides to cycle between opacity 0 or 1, but the outcome is not great and I feel there must be an easier way to achieve this effect. In particular it is problematic having to account for the page position when the main component becomes absolute positioned and requires a 'top' value.
Any advice is appreciated thanks. Sample code is below:
import * as React from 'react';
import { useInView } from 'react-intersection-observer';
import styled from 'styled-components';
const OuterContainer = styled.div`
height: 500vh;
`;
const Card = styled.div`
box-sizing: border-box;
position: fixed;
top: 0;
width: 100%;
height:64vh;
transition: 1s;
z-index: 5;
&.hidden {
opacity: 0;
}
&.show {
opacity: 1;
}
&.border {
position: absolute;
top: 0;
}
`;
const AltCard = styled(Card)`
position: static;
`;
const CardContainer = styled.div`
height: 64vh;
`;
const FirstCard = styled(Card)`
opacity: 1;
`;
const CardGhost = styled.div`
height:64vh;
`;
const LastGhost = styled.div`
box-sizing: border-box;
`;
const GhostContainer = styled.div`
width: 100%;
position: absolute;
top: 0;
`;
const MainContainer = styled.div`
position: fixed;
width: 100%;
top: 0;
&.moving {
position: absolute;
top: 156.5vh;
}
`;
const HeaderBar = styled.div`
top: 64vh;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 8rem;
background-color: #44ff44;
`;
export default function IntroSection() {
const options = { threshold: 0.66 };
const [ref0, visible0] = useInView({ threshold: 0 });
const [ref1, visible1] = useInView(options);
const [ref2, visible2] = useInView(options);
const [ref3, visible3] = useInView(options);
const [ref4, visible4] = useInView({ threshold: 0.33 });
return (
<>
<OuterContainer>
<GhostContainer>
<CardGhost ref={ref0} />
<CardGhost ref={ref1} />
<CardGhost ref={ref2} />
<CardGhost ref={ref3} />
<LastGhost ref={ref4} />
</GhostContainer>
<CardContainer>
<FirstCard
className={visible0 ? 'show' : 'hidden'}
style={{ backgroundColor: 'lightBlue' }}
/>
<Card
className={visible1 ? 'show' : 'hidden'}
style={{ backgroundColor: 'lightGreen' }}
/>
<Card
className={visible2 ? 'show' : 'hidden'}
style={{ backgroundColor: 'lightYellow' }}
/>
</CardContainer>
</OuterContainer>
<MainContainer
className={visible4 && 'moving'}
>
<AltCard
className={visible3 ? 'show' : 'hidden'}
style={{ backgroundColor: '#ffBBFF' }}
/>
<HeaderBar><h1>THIS IS THE NAVBAR</h1></HeaderBar>
</MainContainer>
</>
);
}
I am trying to animate a position change of the active box. When the user clicks on the box, I would like the box to animate a margin-top change and the rest of the boxes to stay at 0px. When the user changes the active box, the previously active box will return to 0px and the new active box will acquire a margin-top of 50px.
I think I am nearly there but I haven't quite managed to get it to work yet. I would be really grateful if someone could help enlighten me as to what I am doing wrong.
import { useSpring, useSprings, animated } from "react-spring";
import styled from "styled-components";
const Nav = () => {
// Set Active Box
const [activeBox, setActiveBox] = useState(0);
const handleClick = (index) => {
setActiveBox(index);
};
// Boxes
const boxes = [box1, box2, box3, box4];
// useSprings
const springs = useSprings(
boxes.length,
boxes.map((box, index) => ({
marginTop: activeBox === index ? 50 : 0,
}))
);
return (
<NavContainer>
{springs.map((prop, index) => (
<StyledBox
style={prop}
key={index}
onClick={() => handleClick(index)}
currentActiveBox={activeBox === index}
>
<img src={boxes[index]} alt="" />
</StyledBox>
))}
</NavContainer>
);
};
export default Nav;
const NavContainer = styled.div`
position: absolute;
bottom: 0;
width: 200px;
height: 75px;
`;
const StyledBox = styled.div`
width: 25px;
height: 25px;
img {
width: 100%;
height: 100%;
}
`;
Thank you!
The issue was that animated was not added to the styled component!
const StyledBox = styled(animated.div)`
width: 25px;
height: 25px;
img {
width: 100%;
height: 100%;
}
In the stepper component that I am working on, I am using the React Styled Components library. Unfortunately, I can't use Material UI or another similar solution. Originally, I was using CSS which rendered all of the UI for the stepper:
{index !== steps.length - 1 && (
<div
className={`divider-line divider-line_${steps.length}`}
/>
)}
This worked, but now I have to use this library, so I converted the I've now converted the horizontal line CSS as styled-components.
styled.js
export const DividerLine = styled.div`
height: 1px;
background-color: blue;
position: absolute;
top: 20%;
left: 70%;
`;
export const DividerLine_2 = styled.div`
width: 296%;
`;
export const DividerLine_3 = styled.div`
width: 125%;
`;
export const DividerLine_4 = styled.div`
width: 70%;
`;
export const DividerLine_5 = styled.div`
width: 60%;
`;
The rest of the stepper animations work but the original code does not render the horizontal lines.
I ran into a similar problem with rendering the numbered bubbles in various states, which I resolved by creating variables to use within inline styling:
let stepColor = '#65CC34';
let stepText = '#ffffff';
let stepTextActive = '#65CC34';
Stepper.js
<StepContainer key={index}>
<StepWrapper>
<StepNumber
style={{
background: `${
step.selected ? stepColor : ''
}`,
color: `${
step.selected ? stepText : stepTextActive
}`,
}}
>
{step.completed ? <span>✓</span> : index + 1}
</StepNumber>
{index !== steps.length - 1 && (
<div
className={`divider-line divider-line_${steps.length}`}
/>
)}
</StepWrapper>
<DividerLine />
</StepContainer>
);
});
return <StepWrapper>{stepsJSX}</StepWrapper>;
}
}
However, I'm not sure how to use {`divider-line divider-line_${steps.length}`} inside of the styled component. Any suggestions?
you don't need to use multiple classes with styled-components. Here's how you can do it:
const dividerLineWidths = {
'2': '296%',
'3': '125%',
'4': '70%',
'5': '50%'
}
export const DividerLine = styled.div`
height: 1px;
background-color: blue;
position: absolute;
top: 20%;
left: 70%;
${({steps}) => steps && `
width: ${dividerLineWidths[steps.length]}
`}
`;
Then:
...
{index !== steps.length - 1 && <DividerLine steps={steps} />}
...
Styled components will dynamically generate a new className for you depending on the props being passed to it. Think of the styled-components consts as full components as opposed to blobs of css properties.
I am trying to change background color of Navbar to white on scrolling, but my code changes the state only in the console.
How to solve it?
Here is React and CSS code
import React, { useState, useEffect } from 'react';
import '../index';
export default function Header() {
const [headerColor, setHeaderColor] = useState('.header container');
const listenScrollEvent = () => {
window.scrollY > 250 ? setHeaderColor('#29323c') : setHeaderColor('transparent');
};
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
window.addEventListener('scroll', listenScrollEvent);
});
console.log(headerColor);
return (
<section id="header" style={{ color: headerColor }}>
<div className="header container" style={{ color: headerColor }}>
/* Header section */
#header {
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100vw;
height: auto;
}
#header .header {
min-height: 8vh;
background-color: rgba(31, 30, 30, 0.24);
transition: 0.3s ease background-color;
}
#header .nav-bar {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 100%;
max-width: 1300px;
padding: 0 10px;
}
I would rephrase your question to: "How does state work in React?"
You seem to be using a component named "Header".
import React, { useState, useEffect } from 'react';
import '../index';
export default function Header() {
const headerColor = useState({ headerColor : 'transparant' });
const listenScrollEvent = () => {
window.scrollY > 250 ? setHeaderColor('#29323c') : setHeaderColor('transparent');
};
//well lets create a func for setHeaderColor
setHeaderColor(color){
this.setState({
headerColor: color
});
}
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
window.addEventListener('scroll', listenScrollEvent);
});
console.log(headerColor);
return (
<section id="header" style={{ background-color: headerColor }}>
<div className="header container" style={{ background-color: headerColor }}>
"Hooks are a new feature in React v16.7.0-alpha useState is the “Hook”. useState() set the default value of the any variable and manage in function component(PureComponent functions). ex : const [count, setCount] = useState(0); set the default value of count 0. and u can use setCount to increment or decrement the value. onClick={() => setCount(count + 1)} increment the count value.DOC
"
Base answer on:
https://stackoverflow.com/a/53166036/4095631
Please also look at:
"Updating an object with setState in React"
Updating an object with setState in React
and the official documents about state and hooks:
https://reactjs.org/docs/hooks-overview.html