How to detect onMouseOver on underlying element in React using its boundaries - reactjs

Can't detect an onMouseOver event on an element underneath a <canvas /> that detects onMouseMove.
I have the <canvas /> that has a particle simulation which depends on the onMouseMove event. I also have a <div /> that lies underneath the <canvas />. I need to detect its onMouseOver within its boundaries. I currently passed the onMouseOver from the wrapper <div /> that wraps <canvas /> and <div /> but it results in handleMouseOver() for <div /> being triggered whenever mouse is over a wrapper.
Structure
<Wrapper>
<canvas width="100%" height="100%" z-index="2" />
<div width="20px" height="20px" z-index="1" />
</Wrapper>
Live example: https://codesandbox.io/s/underneath-event-demo-4uzm0
My task is to catch the onMouseOver for the <div /> that lies underneath the <canvas /> that catches all the events and needs to catch the onMouseMove event too. pointer-events: none is not a solution because I need my <canvas /> to catch events too. Changing z-index results in one of the elements not been available for an event catching.

You can do this
handleCanvasMouseMove
const handleCanvasMouseMove = e => {
console.log("Canvas move event");
console.log("Canvas value X", e.clientX);
console.log("Canvas value Y", e.clientY);
};
call like this
<Canvas onMouseMove={e => handleCanvasMouseMove(e)} />

Related

Pass icon button as props using react

I have a common grid component where I define the structure of the grid and also structure of a button bar that goes on top of the grid.
Common-grid.js
<Box height='100%' width='100%' position='absolute'>
<div className="common-grid">
<div className="button-bar">
</div>
<div className="ag-grid">
</div>
</div>
</Box>
I pass data to the grid from my other component based to fill in the grid.
MyComponent.js
{gridData.length > 0 && <Grid tableData={gridData} columnData={activeListColumnDef} {...props}/>}
Along with the data, I would also like to pass icon buttons that I would like to see in button bar.
<IconButton
icon={<AddIcon />}
onClick={onClickOpenActiveListEditor}
/>
<IconButton
icon={<EditIcon />}
/>
I do not want to define icon buttons in the common component but pass it as props. Is it possible to pass such html elements along with its event listeners as props? Please help!
Sure, it's called a render prop. Just directly pass the node like this:
// in the parent component
<Grid
tableData={gridData}
columnData={activeListColumnDef}
icon={<AddIcon onClick={onClickOpenActiveListEditor} />}
{...props}
/>
// in the Grid component
function Grid({tableData, columnData, icon}){
return (
<>
// grid stuff
{icon && icon}
</>
)
}
If you need typescript support, the node would typed as such:
interface GridProps{
// stuff
icon?: React.ReactNode;
}
You could do something like:
const renderIcon = (onClick) => {
return <Icon onClick={onClick} />
}
...
<IconButton renderIcon={renderIcon} />
Then, inside IconButton:
{renderIcon()}

Material-ui Snackbar pop up out of Screen

Hi!
I go on toy project with React, Material-ui.
when snack bar or react-toastify pop up.
It's not harboring in screen. (RED: scroll up/down then snackbar is there)
I changed pop up position top/bottom. but, It can't cover every case.
How can it make pop up in screen. (GREEN is showing in screen)
I want to SnackBar pop up in "BLUE" position and harboring with scroll.
thanks
<Grid item>
<Grid container direction="row" justify="space-evenly">
<Grid item>
<Button variant="outlined" onClick={() => {
toast.success("Update!")
}}>Update!</Button>
</Grid>
</Grid>
</Grid>
<ToastContainer position="top-center" autoClose={2500} />
I solved it..
I move <ToastContainer/> to top component from sub-component
(from 'Content' to 'Header')
export const App = observer(() => {
const classes = kpopStyle();
return (
<React.Fragment>
<BrowserRouter>
<Header /> // <-- to Here
{storeUiHandler.checkMobile() ?
<div className={classes.contentLayoutMobile}>
<Content /> // <-- from Here
<Footer />
</div> :
<div className={classes.contentLayoutPC}>
<Content />
<Footer />
</div>}
</BrowserRouter>
</React.Fragment>
);
});
now, It works as I expected.

Recharts Event not working when bar chart bar value is 0

I am using Recharts BarChart components to visualize my data. In the Bar component, it supports a few events handler (onClick, onMouseDown, etc).
My question: I have an onClick event handler so users are able to click on the bar chart and redirect to other pages based on the result ID.
My problem: If the bar chart's value is at 0, users are unable to click on the link since onClick event handler is implemented on the bar itself.
Source code:
<BarChart
width={500}
height={500}
layout="vertical"
data={data}
>
<XAxis type="number" />
<YAxis dataKey="title" type="category" />
<Bar
dataKey="score"
fill={Color}
label={<CustomLabel />}
onClick={(data, index) => {
// some logic here
return history.push(`/${data.x.y.id}`);
}}
/>
</BarChart>
Screenshot:
My attempt:
I tried to look at a possible solution and observe the examples on the API in recharts website, I don't see anything that is able to solve my problem. I also tried to have onClick on the title on axis or bar, but the component does not support the feature. Please advise.
You can add an onClick attribute on the BarChart component and check data.activePayload[0] to see which bar chart has been clicked.
<BarChart
width={500}
height={500}
layout="vertical"
data={data}
onClick={(data) => {
// do your history.push based on data.activePayload[0]
if (data && data.activePayload && data.activePayload.length > 0) {
return history.push(`/${data.activePayload[0].x.y.id}`);
}
}}
>
<XAxis type="number" />
<YAxis dataKey="title" type="category" />
<Bar
dataKey="score"
fill={Color}
label={<CustomLabel />}
/>
</BarChart>

React-Vis - How Do I render an empty chart area?

I'm working on a react-vis chart that will dynamically update the data that is displayed when a user clicks on/off the legend item for that series.
If a user clicks clicks off all of the series the JSX that I render essentially looks like this:
<div>
<XYPlot
xDomain={paretoOrder}
margin={{left: 150, bottom: 150}}
width={450}
height={450}
xType="ordinal"
stackBy="y"
>
<VerticalGridLines />
<HorizontalGridLines />
<XAxis
tickLabelAngle={-45}
/>
<YAxis
tickFormat={ tick => translator.formatTime(tick, {hideZero: true})}
/>
<VerticalBarSeries
data={[]}
/>
</XYPlot>
<DiscreteColorLegend
orientation="horizontal"
width={300}
items={legendItems}
onItemClick={this.onLegendClick}
/>
</div>
I would expect that this would still render the axes, the grid lines, etc, but the entire chart is removed from the DOM instead. How do I render a chart with empty data but keep the axes, grid lines, etc in the DOM?
Add dontCheckIfEmpty prop (as true, default is false) to <XYPlot> tag.
<XYPlot
dontCheckIfEmpty
>
<XAxis/>
<YAxis/>
<VerticalBarSeries
data={data}
/>
<VerticalGridLines />
<HorizontalGridLines />
</XYPlot>

how to visible tooltip always in react slider

I am using react slider with tooltip.
<Slider
min={ set_min(this.state.myValue) }
max={ set_max(this.state.myValue) }
defaultValue={ set_def(this.state.myValue) }
handle={handle}
toolTipVisibleAlways = {true}
/>
<Tooltip
className = "tooltip-custom"
prefixCls="rc-slider-tooltip"
overlay={percentFormatter(value, this.state.myValue) }
visible={dragging}
placement="top"
key={index}
delayShow = {300}
delayHide = {150}
>
<Handle value={value} {...restProps} />
</Tooltip>
all things are good and well-displayed.
what i want to know is that how can i make tooltip always visible.
I searched this answer on the internet and found two answers.
first one is toolTipVisibleAlways = {true}
and second one is
delayShow = {300}
delayHide = {150}
But as you can see my code, nothing changed.
Use tipProps props exposed after Slider wrapped by createSliderWithTooltip. Example below should work as tipProps will pass the props to rc-tooltip component.
Read here for detailed explanation and also see this example provided by rc-slider
.
<Slider
min={ set_min(this.state.myValue) }
max={ set_max(this.state.myValue) }
defaultValue={ set_def(this.state.myValue) }
handle={handle}
tipProps={{visible:true}}
/>
I solved this issue by making my own inside the handle. This way the text will always move with the handle.
<SliderTooltip
prefixCls="rc-slider-tooltip"
visible={dragging}
placement="top"
key={index}
defaultVisible={true}
visible={true}
align={{
offset: [0, -5],
}}
>
<Handle value={value} {...restProps}>
<span>{value}</span>
</Handle>
</SliderTooltip>

Resources