Issues With ZIndex using reactjs and a fixed navbar - css

I have read through many posts/information about Z index and still have not been able to figure this out, I have a website with the navbar position fixed so it stays on the top of the page on scroll, when I get down below my header (component where the navbar is placed), all the elements appear ABOVE the navbar when scrolled over (which is obviously not desired), I am able to put a zIndex of -1 on those elements to fix this, however currently I have a form, and making its zIndex -1 makes all the form inputs and submit button disabled or unclickable (guessing it puts the form below another div/element), so I'm pretty stuck and appreciate any advice .. :)
Navbar.js
import React, { Component } from "react";
import Radium from "radium";
class NavBar extends Component {
state = {
topOfPage: true,
headerSection: true
};
componentDidMount() {
window.addEventListener("scroll", this.navBarState);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.navBarState);
}
navBarState = () => {
if (window.scrollY < 58) {
this.setState({
topOfPage: true
});
}
if (window.scrollY > 58 && window.scrollY < 740) {
this.setState({
topOfPage: false,
headerSection: true
});
}
if (window.scrollY > 740) {
this.setState({
headerSection: false
});
}
};
render() {
const { topOfPage, headerSection } = this.state;
let navStyle;
let linkStyle;
if (topOfPage && headerSection) {
navStyle = {
base: {
background: "transparent",
transition: "background-color 0.7s ease"
}
};
linkStyle = {
base: {
transition: "font-size 0.8s",
":hover": {
color: "black",
fontSize: "25px",
fontWeight: "bold",
background: "white",
textTransform: "uppercase",
paddingTop: "10px",
borderRadius: "50px"
}
}
};
} else if (!topOfPage && headerSection) {
navStyle = {
base: {
background: "rgba(20, 20, 20, 0.87)",
boxShadow: "0 8px 6px -6px",
transition: "background-color 0.7s ease"
}
};
linkStyle = {
base: {
transition: "font-size 0.5s",
":hover": {
color: "white",
fontSize: "25px",
fontWeight: "bold"
}
}
};
} else {
navStyle = {
base: {
background: "rgba(20, 20, 20, 0.99)",
boxShadow: "0 8px 6px -6px"
}
};
linkStyle = {
base: {
transition: "font-size 0.5s",
":hover": {
color: "white",
fontSize: "25px",
fontWeight: "bold"
}
}
};
}
return (
<nav style={[navStyle.base]}>
<ul className="navbarWrapper">
<li>
<a href="#!" style={[linkStyle.base]} key="1">
Home
</a>
</li>
<li>
<a href="#!" style={[linkStyle.base]} key="2">
Beat Store
</a>
</li>
<li>
<a href="#!" style={[linkStyle.base]} key="3">
Licensing
</a>
</li>
<li>
<a href="#!" style={[linkStyle.base]} key="4">
Drum Kits
</a>
</li>
<li>
<a href="#!" style={[linkStyle.base]} key="5">
Contact Us
</a>
</li>
</ul>
</nav>
);
}
}
export default Radium(NavBar);
Form.js
import React from "react";
import { Form, Button, Grid, Segment, Input } from "semantic-ui-react";
const FreeBeatForm = () => {
return (
<Grid
container
style={{
marginTop: "50px",
display: "flex",
justifyContent: "center",
}}
>
<Grid.Column width={5} style={{zIndex: '-1'}}>
<Segment>
<h1>Subscribe</h1>
<Form>
<Form.Field>
<label>Name</label>
<Input placeholder="Name" />
</Form.Field>
<Form.Field>
<label>Email</label>
<Input placeholder="Email" />
</Form.Field>
<Button type="submit">Submit</Button>
</Form>
</Segment>
</Grid.Column>
</Grid>
);
};
export default FreeBeatForm;

Try to leave out the z-index for your components in the page, instead make sure your NavBar as position:fixed and it has a higher z-index, for example you could use 1000.

I'm guessing it has something to do with the semantic ui components, because changing my semantic Inputs to bootstrap inputs fixed the issue..

Related

Doing custom hover animation on nav items(bootstrap nav) but the effect isn't visible in my react application

I'm trying to add custom hover effect on my nav Items using ext CSS but when I import it in my Navbar the bootstrap isn't overwritten and the effect isn't visible and also when the navBar collapses the three line isn't visible but when I click on the top right corner it's there and works fine
**
Here is my NAVBAR.JS file for react
**
import React, { Component } from 'react';
import { Navbar, Nav, Button } from 'react-bootstrap';
import styles from './Navbar.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Link } from 'react-router-dom';
const links = [
{
href: '/novels/601e73a75e4fd540506c9938',
text: 'Novel',
},
{ href: '#', text: 'Buy EA Coins' },
{ href: '#', text: 'Get Started' },
{ href: '#', text: 'Library' },
{ href: '/', text: 'home' },
];
const createNavItem = ({ href, text, className }) => (
<Nav.Item>
<Nav.Link className={className}>
<Link to={href}> {text}</Link>
</Nav.Link>
</Nav.Item>
);
class NavbarMain extends Component {
constructor(props) {
super(props);
this.state = {
key: 'home',
};
this.handleSelect = this.handleSelect.bind(this);
}
handleSelect(key) {
this.setState({
key: key,
});
alert(`selected ${key}`);
}
render() {
return (
<Navbar
bg="light"
variant="danger"
expand="lg"
fixed-top
className={styles.test}
>
<Navbar bg="light">
<Navbar.Brand>
<Link to="/" exact>
<img
src="EA-Logo-edit.png"
width="90"
height="70"
margin="none"
className="d-inline-block align-top"
alt="React Bootstrap logo"
style={{ margin: 'none' }}
/>
</Link>
</Navbar.Brand>
</Navbar>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto" activeKey="/" className={styles.avbar}>
{links.map(createNavItem)}
</Nav>
<Nav className="ml-auto" navbar>
<Nav.Item>
<Nav.Link href="#discord">
<Button variant="outline-dark">
<img height={25} width={40} src="discord.svg" alt="" />
Discord
</Button>
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link href="/auth/login">
<Button variant="outline-dark">
<img height={25} width={40} src="google.svg" alt="" />
Login
</Button>
</Nav.Link>
</Nav.Item>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
}
export default NavbarMain;
Here is my CSS file
:local(.navbar.hover::before){
position: relative;
}
:local(.navbar:before){
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: #000;
visibility: hidden;
transform: scaleX(0);
transition: all 0.3s ease-in-out 0s;
}
:local(.navbar:hover){
color: #000;
}
:local(.navbar){
position: relative;
color: #000;
text-decoration: none;
}
You can fix overwrite problem with !important like this
:local(.navbar:hover){
color: #000 !important;
}

Hide nav button in react-material-ui-carousel

I've just implemented the react material ui carousel, and it was pretty straightforward, the only thing i didn't catch, is how to hide buttons and show them only on over.
I noticed the props navButtonsAlwaysVisible and set it to false but it isn't enough.
Should i implement my own logic for that, or maybe I'm just missing something?
here's the component code:
import styles from '../../styles/Testimonial.module.scss'
import Image from 'next/image'
import Carousel from 'react-material-ui-carousel'
const Testimonial = _ => {
const items = [
{
imageUrl: "/png/image0.webp",
feedback: "feedback0",
name: "name0",
location: "location0"
},
{
imageUrl: "/png/image1.jpeg",
feedback: "feedback1",
name: "name1",
location: "location1"
}
]
return (
<div id="customers" className={`section ${styles.testimonial}`}>
<h2 className={`title ${styles.title}`}>Clientes Felizes</h2>
<span className={"separator"}> </span>
<Carousel
className={styles.carousel}
autoPlay={true}
stopAutoPlayOnHover={true}
interval={5000}
animation={"slide"}
swipe={true}
navButtonsAlwaysVisible={false}
navButtonsProps={{
style: {
backgroundColor: "#8f34eb",
opacity: 0.4
}
}}
>
{
items.map( (item, i) => <Item key={i} item={item} /> )
}
</Carousel>
</div>
)
}
function Item(props)
{
return (
<article className={styles.testimonial__card}>
<div className={styles.testimonial__photo_container}>
<Image
className={styles.testimonial__photo}
src={props.item.imageUrl}
alt="Testimonial"
width={312}
height={300}
/>
</div>
<p className={styles.testimonial__copy}>{props.item.feedback}</p>
<span className={styles.testimonial__name}>{props.item.name}</span>
<span className={styles.testimonial__city}>{props.item.location}</span>
</article>
)
}
export default Testimonial;
there's a prop called navButtonsAlwaysInvisible
navButtonsAlwaysInvisible={true}
You can try using Custom CSS for your purpose. Based on the current rendered markup,
.jss6 {
opacity: 0;
transition: all ease 1000ms; /* So that it does not disappear quickly */
}
You can define the hover for the parent so that it displays only when the parent container is hovered on:
.jss1.Testimonial_carousel__3rny3:hover .jss6 {
opacity: 1;
}
This is how it works now:

Change scrollbar by hover. (React /css) - Material-UI

I have a scrollbar in multiple lists in the React app.
My global CSS within Material-UI is:
MuiCssBaseline: {
...theme.overrides?.MuiCssBaseline,
'#global': {
'#font-face': fontFace,
'*::-webkit-scrollbar': {
width: '1.3%',
maxWidth: '5px'
},
'*::-webkit-scrollbar-thumb': {
backgroundColor: 'white'
},
'*:focus': {
outline: 'none'
}
}
}
};
I am trying to add global state for hover.
When I hover on the box(!) not on the scroll itself, the scrollbar should be changed to gray.
Let's say I have box like:
<Box className={listStyle.root}>
<AutoSizer>
{({ height, width }) => (
<List dense ......
return (
<ListItem
/>
);
})}
</List>
)}
</AutoSizer>
I tried something like the following and it's not working:
.listStyle:{
'&:hover':{
'*::-webkit-scrollbar-thumb': {
backgroundColor: 'gray'
},
}
}
How can I achieve that?
The primary issue I see is that when nesting a rule (e.g. ::-webkit-scrollbar-thumb pseudo-element within :hover pseudo-class), you need to use & to refer to the parent rule instead of using *. So your listStyle should look like:
.listStyle:{
'&:hover':{
'&::-webkit-scrollbar-thumb': {
backgroundColor: 'gray'
},
}
}
It would also be equivalent to do the following:
.listStyle:{
'&:hover::-webkit-scrollbar-thumb': {
backgroundColor: 'gray'
}
}
If you want to apply this globally, you can do something like the following (I've changed the colors just to make the effects more easily distinguishable from browser defaults):
const theme = createMuiTheme({
overrides: {
MuiCssBaseline: {
"#global": {
"*::-webkit-scrollbar": {
width: "1.3%",
maxWidth: "5px"
},
"*::-webkit-scrollbar-thumb": {
backgroundColor: "purple"
},
"*:hover": {
"&::-webkit-scrollbar-thumb": {
backgroundColor: "green"
}
}
/* Equivalent alternative:
"*:hover::-webkit-scrollbar-thumb": {
backgroundColor: "green"
}
*/
}
}
}
});
Here is a full example showing both the global approach and overriding that using a class name at a lower level:
import React from "react";
import CssBaseline from "#material-ui/core/CssBaseline";
import {
ThemeProvider,
createMuiTheme,
makeStyles
} from "#material-ui/core/styles";
const theme = createMuiTheme({
overrides: {
MuiCssBaseline: {
"#global": {
"*::-webkit-scrollbar": {
width: "1.3%",
maxWidth: "5px"
},
"*::-webkit-scrollbar-thumb": {
backgroundColor: "purple"
},
"*:hover": {
"&::-webkit-scrollbar-thumb": {
backgroundColor: "green"
}
}
/* Equivalent alternative:
"*:hover::-webkit-scrollbar-thumb": {
backgroundColor: "green"
}
*/
}
}
}
});
const useStyles = makeStyles({
divStyle: {
"&:hover::-webkit-scrollbar-thumb": {
backgroundColor: "red"
}
}
});
export default function App() {
const classes = useStyles();
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<div style={{ height: "200px", overflowY: "scroll" }}>
<h1>
Div with enough content to scroll. Globally controlled scrollbar hover
color
</h1>
<h2>1</h2>
<h2>2</h2>
<h2>3</h2>
<h2>4</h2>
<h2>5</h2>
<h2>6</h2>
</div>
<div
style={{ height: "200px", overflowY: "scroll" }}
className={classes.divStyle}
>
<h1>
Div with enough content to scroll. Scrollbar hover color controlled by
classes.divStyle.
</h1>
<h2>1</h2>
<h2>2</h2>
<h2>3</h2>
<h2>4</h2>
<h2>5</h2>
<h2>6</h2>
</div>
</ThemeProvider>
);
}

How to position tooltip on the top of a barchart in rechart?

Problem:
I have created a bar chart with a custom tooltip. Now What I need is to position tooltip on top of the bar not within the area of the chart. Like in this picture.
This is how It looks like now.
Here I am providing how I organize my code.
import React, { Component } from "react";
import {
BarChart,
Tooltip,
Bar,
Legend,
ResponsiveContainer,
Cell
} from "recharts";
import { Card, CardTitle, CardBody } from "reactstrap";
import "./SessionDuration.css";
const colors = ["#26a0a7", "#79d69f", "#f9ec86", "#ec983d"];
const data = [
{
name: "Page A",
pv: 2400,
amt: 2400
},
{
name: "Page B",
pv: 1398,
amt: 2210
},
{
name: "Page C",
pv: 9800,
amt: 2290
},
{
name: "Page D",
pv: 3908,
amt: 2000
}
];
const getTitleOfTooltip = (label) =>{
if (label === 0) {
return "<=5 min";
}
if (label === 1) {
return "5-30 min";
}
if (label === 2) {
return "30-60 min";
}
if (label === 3) {
return ">60";
}
}
const getIntroOfPage = label => {
if (label === 0) {
return "Page A is about men's clothing";
}
if (label === 1) {
return "Page B is about women's dress";
}
if (label === 2) {
return "Page C is about women's bag";
}
if (label === 3) {
return "Page D is about household goods";
}
};
class SessionDuration extends Component {
render() {
return (
<Card className="session-duration-card">
<CardTitle className="session-duration-card-header">
Session Duration
</CardTitle>
<CardBody>
<ResponsiveContainer width="100%" height="100%" aspect={4.0 / 5.5}>
<BarChart
data={data}
margin={{
top: 3,
right: 5,
left: 5,
bottom: 13
}}
barGap={10}
>
<Tooltip
coordinate={{ x: 0, y: 150 }}
content={<CustomTooltip />}
/>
<Bar dataKey="pv" fill="#8884d8">
{data.map((entry, index) => (
<Cell key={`cell-${index + 1}`} fill={colors[index]} />
))}
</Bar>
</BarChart>
</ResponsiveContainer>
</CardBody>
</Card>
);
}
}
export default SessionDuration;
const CustomTooltip = ({ active, payload, label }) => {
if (active) {
return (
<div className="session-duration-tooltip">
<p className="session-duration-tooltip-label">{getTitleOfTooltip(label)}</p>
<p className="session-duration-tooltip-intro">
{getIntroOfPage(label)}
</p>
<p className="session-duration-tooltip-desc">
Anything you want can be displayed here.
</p>
</div>
);
}
return null;
};
Here I am providing my CSS file.
#media only screen and (min-width: 1024px) {
.session-duration-card {
margin-top: 14.5%;
margin-left: -44%;
width: 190% !important;
border-radius: none !important;
height: 86%
}
.session-duration-card-header {
font-weight: 700;
text-align: left;
padding-left: 6%
}
.session-duration-tooltip {
width: 210%;
}
.session-duration-tooltip-label {
font-weight: 700;
font-size: 11px;
}
}
#media only screen and (min-width: 308px) and (max-width: 1024px) {
.session-duration-card {
margin-top: 5%;
margin-left: 3.2%;
width: 94.5%;
border-radius: none !important;
}
.session-duration-card-header {
font-weight: 700;
text-align: center;
}
}
#media only screen and (min-width: 1666px) {
.session-duration-card {
margin-top: 11%;
margin-left: -13%;
width: 190% !important;
height: 97%;
border-radius: none !important;
}
.session-duration-card-header {
font-weight: 700;
text-align: center;
}
}
I tried a lot to find a solution for my problem but I was unable to get it done can someone help me by modifying my code to get this work done. Thank you very much.
To solve this problem, will need to get the height and width of each bar and tooltip.
Need two functions onMouseMove and onMouseOut to get the height
and width of the Bar component.
Using useState to get and keep the height and width to the state, also place extra boolean to the state, to handle when the mouse is outside of the Bar. (So, to function we add object with two paramets data and boolean ).
In the Tooltip component, set the position object for static values X, Y and using the state values, set the height and width.
Using useEffect, to find the .recharts-tooltip-wrapper class, to define the height and width of the DOM element.
Set styles for .recharts-tooltip-wrapper. (Rechart. js in .recharts-tooltip-wrapper has its own generated style, we need to keep some static style of the .recharts-tooltip-wrapper and add our).
SessionDuration.js
import React, { useState, useEffect } from 'react';
import { BarChart, Tooltip, Bar, ResponsiveContainer, Cell } from 'recharts';
import { Card, CardTitle, CardBody } from 'reactstrap';
import './SessionDuration.css';
const colors = ['#26a0a7', '#79d69f', '#f9ec86', '#ec983d'];
const data = [
{
name: 'Page A',
pv: 2400,
amt: 2400,
},
{
name: 'Page B',
pv: 1398,
amt: 2210,
},
{
name: 'Page C',
pv: 9800,
amt: 2290,
},
{
name: 'Page D',
pv: 3908,
amt: 2000,
},
];
const getTitleOfTooltip = label => {
if (label === 0) {
return '<=5 min';
}
if (label === 1) {
return '5-30 min';
}
if (label === 2) {
return '30-60 min';
}
if (label === 3) {
return '>60';
}
};
const getIntroOfPage = label => {
if (label === 0) {
return "Page A is about men's clothing";
}
if (label === 1) {
return "Page B is about women's dress";
}
if (label === 2) {
return "Page C is about women's bag";
}
if (label === 3) {
return 'Page D is about household goods';
}
};
export const SessionDuration = () => {
const [position, setPosition] = useState(null);
useEffect(() => {
const tooltip = document.querySelector('.recharts-tooltip-wrapper');
if (!tooltip) return;
// Init tooltip values
const tooltipHeight = tooltip.getBoundingClientRect().height;
const tooltipWidth = tooltip.getBoundingClientRect().width;
const spaceForLittleTriangle = 10;
// Rewrite tooltip styles
tooltip.style = `
transform: translate(${position?.data.x}px, ${position?.data.y}px);
pointer-events: none; position: absolute;
top: -${tooltipHeight + spaceForLittleTriangle}px;
left: -${tooltipWidth / 2 - position?.data.width / 2}px;
opacity: ${position?.show ? '1' : 0};
transition: all 400ms ease 0s;
`;
}, [position]);
return (
<>
<Card className="session-duration-card">
<CardTitle className="session-duration-card-header">
Session Duration
</CardTitle>
<CardBody>
<ResponsiveContainer width="100%" height="100%" aspect={4.0 / 5.5}>
<BarChart
data={data}
margin={{
top: 100, // for tooltip visibility
right: 5,
left: 5,
bottom: 13,
}}
barGap={10}
>
<Tooltip
cursor={false} // hide hover effect 'grey rectangle'
position={{
// Static position
x: position?.data.x ?? 0,
y: position?.data.y ?? 0,
}}
content={<CustomTooltip />}
/>
<Bar
dataKey="pv"
fill="#8884d8"
// Handlers
onMouseMove={data => setPosition({ data: data, show: true })}
onMouseOut={data => setPosition({ data: data, show: false })}
>
{data.map((entry, index) => (
<Cell key={`cell-${index + 1}`} fill={colors[index]} />
))}
</Bar>
</BarChart>
</ResponsiveContainer>
</CardBody>
</Card>
</>
);
};
export default SessionDuration;
const CustomTooltip = ({ active, payload, label }) => {
if (active) {
return (
<div className="session-duration-tooltip">
<p className="session-duration-tooltip-label">
{getTitleOfTooltip(label)}
</p>
<p className="session-duration-tooltip-intro">
{getIntroOfPage(label)}
</p>
<p className="session-duration-tooltip-desc">
Anything you want can be displayed here.
</p>
</div>
);
}
return null;
};
SessionDuration.css
:root {
--bg-color: hsl(270 3% 29% / 0.9);
}
.session-duration-tooltip {
max-width: 250px;
position: relative;
padding: 0.5em;
border-radius: 5px;
background-color: var(--bg-color);
color: aliceblue;
}
.session-duration-tooltip::after {
content: '';
height: 0;
width: 0;
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
border-style: solid;
border-width: 10px 10px 0 10px;
border-color: var(--bg-color) transparent transparent transparent;
}
A lot of people asking for this feature here https://github.com/recharts/recharts/issues/222 and here https://github.com/recharts/recharts/issues/488. I came up with
Third working solution (with great help from #ЖнецЪ answer)
Unfortunately the problem with that answer is that you still have to hover the "bars" themselves, and mine are quite narrow, so I wanted it to show up regardless of if you are hovering the bar or the "cursor area", this solution allows the latter.
Basically:
Get the active tooltip index from the full barchart (changes on the cursor area and not the specific bar)
a useEffect hook grabs all the bars using the bar class ".recharts-bar-rectangle" and grabs the current active one using the toolTipIndex, get's the height, and sets that to the tooltip Y-position.
As before the tooltip is controlled by the internal x position but the y position is the height +/- some offset.
export default function BarChartCard(props) {
const [activeBarIndex, setActiveBarIndex] = useState();
const [toolTipYPosition, setToolTipYPosition] = useState({});
useEffect(() => {
const barCharts = document.querySelectorAll(".recharts-bar-rectangle");
if (!barCharts || !activeBarIndex) return;
// Init tooltip values
const barChart = barCharts[activeBarIndex];
setToolTipYPosition(barChart.getBoundingClientRect().height);
}, [activeBarIndex]);
return (
<BaseCard>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="h2">{props.title}</Typography>
</Grid>
</Grid>
<ResponsiveContainer width={"100%"} height={300}>
<BarChart
barGap={0}
data={props.data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
onMouseMove={(e) => {
setActiveBarIndex(e.activeTooltipIndex);
}}
>
<Tooltip
content={<CustomTooltip />}
cursor={false}
position={{ y: 170 - toolTipYPosition }}
offset={-60}
allowEscapeViewBox={{ x: true, y: true }}
/>
<XAxis
style={{
fontSize: "1.125rem",
fontFamily: "Cairo",
fontWeight: 600,
}}
axisLine={false}
tickLine={false}
dataKey="date"
tickFormatter={ReformatDateShortDayName}
/>
<YAxis
allowDecimals={false}
style={{
fontSize: "1.125rem",
fontFamily: "Cairo",
fontWeight: 600,
}}
dataKey="value"
axisLine={false}
tickLine={false}
/>
<Legend
style={{
fontSize: "1.125rem",
fontFamily: "Cairo",
fontWeight: 600,
}}
iconType="circle"
iconSize={6}
align="right"
verticalAlign="top"
height={36}
formatter={(value) => (
<span
style={{
color: "#CCC",
fontSize: "1.125rem",
fontWeight: 600,
fontFamily: "Cairo",
}}
>
{value}
</span>
)}
/>
<Bar
barSize={10}
dataKey="value"
name={props.legendText}
fill="#EFC92B"
/>
</BarChart>
</ResponsiveContainer>
</BaseCard>
);
}
A hacky solution
based on some other implementation and answers out there:
const [barGraphData, setBarGraphData] = useState({})
return (
<BarChart barGap={0} data={props.data} margin={{
top: 5,
right: 30,
left: 20,
bottom: 5
}}>
<Tooltip content={<CustomTooltip />}
cursor={{ fill: 'transparent' }}
position={{ y: barGraphData.height + 40}}
offset={-60}
/>
<XAxis />
<YAxis />
<Legend />
<Bar
barSize={10}
dataKey="value"
fill="#EFC92B"
onMouseOver={(data)=> {
setBarGraphData(data)
}}
onMouseLeave={(data) => {
setBarGraphData(data)
}}
/>
</BarChart>
)
So basically:
Have a static y-value, in this case I'm doing the height of the bar + some offset (at least I think it's the height of the bar). But this one could be static as well.
Add an offset to the tooltip, I had to do this otherwise it would not be on top of the bar but right shifted 60 pixels.
Let the x coordinate be handled by recharts.
As you can see from my code, I used a custom tooltip according to the recharts documentation
const CustomTooltip = ({ active, payload, label }) => {
const classes = useStyles();
return (
<Fragment>
{active && payload?.length >= 1 &&
<Card className={classes.toolTip}>
<CardContent className={classes.toolTipContent}>
<Typography className={classes.toolTipLabel}>{label}</Typography>
<Typography className={classes.toolTipValue}>{payload[0].payload.value}</Typography>
</CardContent>
</Card>
}
</Fragment>
)
}
But this is just for formatting / style, it should work with the default one as well.
Unfortunately this only seems to work when you hover the actual "Bar" and not the full area as defined by the "cursor".
Second hacky solution, which works for the full cursor area
This led me to a second solution which unfortunately gives an warning
Warning: Cannot update a component (`BarChartCard`) while rendering a different component (`label`). To locate the bad setState() call inside `label`, follow the stack trace as described in ...
The code to create get it going is here, any comment on how to make this work would be awesome!
export default function BarChartCard(props) {
const [barGraphData, setBarGraphData] = useState({});
const [activeBarIndex, setActiveBarIndex] = useState({});
const [toolTipYPosition, setToolTipYPosition] = useState({});
return (
<BaseCard>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="h2">{props.title}</Typography>
</Grid>
</Grid>
<ResponsiveContainer
width={"100%"}
height={300}
>
<BarChart
barGap={0}
data={props.data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
onMouseMove={(e) => {
setActiveBarIndex(e.activeTooltipIndex)
}}
>
<Tooltip
content={<CustomTooltip />}
cursor={false}
position={{ y: -toolTipYPosition + 170}}
offset={-60}
allowEscapeViewBox={{ x: true, y: true }}
/>
<XAxis
style={{
fontSize: "1.125rem",
fontFamily: "Cairo",
fontWeight: 600,
}}
axisLine={false}
tickLine={false}
dataKey="date"
tickFormatter={ReformatDateShortDayName}
/>
<YAxis
allowDecimals={false}
style={{
fontSize: "1.125rem",
fontFamily: "Cairo",
fontWeight: 600,
}}
dataKey="value"
axisLine={false}
tickLine={false}
/>
<Legend
style={{
fontSize: "1.125rem",
fontFamily: "Cairo",
fontWeight: 600,
}}
iconType="circle"
iconSize={6}
align="right"
verticalAlign="top"
height={36}
formatter={(value) => (
<span
style={{
color: "#CCC",
fontSize: "1.125rem",
fontWeight: 600,
fontFamily: "Cairo",
}}
>
{value}
</span>
)}
/>
<Bar
label={(e) => {
if(e.index === activeBarIndex){
setToolTipYPosition(e.height)
}
return null;
}}
barSize={10}
dataKey="value"
name={props.legendText}
fill="#EFC92B"
onMouseOver={(data) => {
setBarGraphData(data);
}}
onMouseLeave={(data) => {
setBarGraphData(data);
}}
/>
</BarChart>
</ResponsiveContainer>
</BaseCard>
);
}

How to display three post photo div at the bottom of the page using Reactjs and Css

The code below has three posts photos in the array. When I click on each post button am supposed to be seeing
Three post Photo div that corresponds to each post all at the bottom.
My Problem:
My issue is that it is showing just one post photo div which keeps replacing others after I added the CSS code below.
const mainArea={
position: 'fixed',
width: '80%',
bottom: '0%',
display: 'inline-block'
}
const photodiv={
position: 'relative',
width: '250px',
// height:auto,
background: 'orange',
color: 'black',
borderRadius: '5px 5px 0px 0px',
bottom: '0px',
}
screenshot showing jammed div based on the CSS implementation
What I want:
I need to be seeing three div post photos if the three toggle button is clicked
Here is the main code
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
const mainArea={
position: 'fixed',
width: '80%',
bottom: '0%',
display: 'inline-block'
}
const photodiv={
position: 'relative',
width: '250px',
// height:auto,
background: 'orange',
color: 'black',
borderRadius: '5px 5px 0px 0px',
bottom: '0px',
}
class Focus extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
shown: true,
};
}
componentDidMount() {
this.setState({
data: [
{ id: "1", title: "my first title", image: "http://localhost/apidb_react/1.png", visible: true , photoVisible: true},
{ id: "2", title: "my second title", image: "http://localhost/apidb_react/2.png", visible: true, photoVisible: true},
{ id: "3", title: "my third title", image: "http://localhost/apidb_react/3.png", visible: true, photoVisible: true}
]
});
}
toggle(id) {
const newData = this.state.data.map(item => {
if(item.id === id) {
return { ...item, visible: !item.visible};
}
return item;
})
this.setState({
data: newData
});
}
/*
hideUnhidePhoto(id) {
const newData = this.state.data.map(item => {
alert(id);
if(item.id === id) {
alert('ttto ' +item.id);
return { ...item, photoVisible: !item.photoVisible};
}
return item;
})
this.setState({
data: newData
});
}
*/
hideUnhidePhoto(id) {
this.setState(({ data }) => {
return {
data : data.map(item => ({
...item,
photoVisible : (id == item.id) ? !item.photoVisible : item.photoVisible }))
}
});
}
render() {
return (
<div>
<label>
<ul>
{this.state.data.map((post, i) => (
<li key={i}>
<div style={mainArea}>
<div style={photodiv}>
<div style={{ display: post.visible ? "none" : "block"}}>
<b>Post Data:</b> {post.title} --{post.id} <br />
<span style={{color: 'red'}} onClick={ () => this.hideUnhidePhoto(post.id) }> Hide/Unhide Photo</span>
<div style={{ display: post.photoVisible ? "block" : "none"}}>
<img src={post.image} />
</div>
</div></div>
</div>
<button onMouseDown={ () => this.toggle(post.id) }>Toggle </button><br />
<br />
</li>
))}
</ul>
</label>
</div>
);
}
}
If I understand the issue correctly, then this can be fixed by adjusting your mainArea style object like so:
const mainArea={
/* position: 'fixed', Remove position fixed */
width: '80%',
bottom: '0%',
display: 'inline-block'
}
The fixed position basically has the effect of placing elements at a location on screen, relative to the client area of the window. This means that if you have multiple elements that share the same (default) coordinates, and are positioned with the fixed rule, then those elements will effectively overlap one another. This gives the appearance of only one element being visible at any given time.
For a working example, see this jsFiddle:
enter link description here
Hope that helps!

Resources