React big Calendar onhover a cell in day view - reactjs

Is it possible to change a colour of a date cell in day view on hover in React big calendar?

You can apply custom classes to events, using the eventPropGetter prop, and use the css :hover CSS pseudo selector to change background color of events.
http://jquense.github.io/react-big-calendar/examples/index.html#prop-eventPropGetter
const customEventPropGetter = ({event, start, end, isSelected}) => {
const myClasses = ['my-custom-event']; // add to every event
if (event.someProp === 'foo') {
myClasses.push('foo-event'); // conditionally add to some events
}
return { className: myClasses, style: {} };
};
// custom sass
.my-custom-event {
&.foo-event {
background-color: red;
&:hover {
background-color: maroon;
}
}
}

Related

AntD table - change cell color on mouse hover

I'm trying to change background color of the cell in antD table using onCell property and onMouseOver function, but without success.
onCell: (record, rowIndex) => {
return {
onMouseOver: () => {
console.log("record, row", record, rowIndex);
return {
props: {
style: { background: "yellow", fontWeight: "bold" }
}
};
}
};
}
Working sandbox example:
demo
Any help would be highly appreciated.
If the goal is to add a custom background on hover to the cells of a certain column, perhaps a simple solution would be adding this as a custom class with onCell.
Forked demo with modification: codesandbox
onCell: (record, rowIndex) => {
return {
className: "custom",
};
};
In CSS, define :hover styles with a higher specificity so that it overrides default style for selected cells:
.ant-table-cell.ant-table-cell-row-hover.custom:hover {
background-color: hotpink;
color: white;
}

How can I "decouple" a state var from its value so that in certain operations the value no longer updates on state change?

I am, just for fun, writing a simple paint program. It has a <Canvas> that creates [color, setColor] with useState and passes them to its children, a <ColorSelector> and a grid of <Cell>s. Clicking a color in the ColorSelector updates color, and clicking a Cell sets its background to color.
The problem is of course that when you click a different color in ColorSelector and it updates color, it cascades down and changes all the currently painted pixels to the new color too. Normally that's the point of state vars, so maybe state isn't what I actually want here.
How can I let Cells always know the current color value but, once applied, keep the background color unchanged until the next click?
maybe try to pass the new color in a deep copy if I understand what you mean to
Yonatan's answer got me on the right track to find the solution.
What I'd been doing: As described in my comment there, each <Cell> had an isPainted boolean and rendered a <CellContents> child which got an onClick that sets isPainted to true, and a className that maps to the selected color iff isPainted is true. Written that way, it didn't matter if I used color or a copy with e.g. color.concat(). Either way, when color changed, the Cell rerendered and got the new color.
What ended up working:
I eliminated the boolean middle-man and made onClick set isPainted to color (don't even need to make a copy) and made CellContent use the value of isPainted (which I should probably rename now) directly to get its the className.
Why it worked
I think this is what's going on, but encourage anyone more knowledgeable to chime in!
Previously I had if (isPainted) { className = color } in the body of Cell, so whenever a cell got re-rendered, its className would change. Now coloris only accessed in event handlers, so now when a Cell is re-rendered, it gets new handlers that use the new colors, but they don't actually do anything until the associated event happens.
Code
Here's the complete working solution
(NOTE: the state var I've been calling color has been renamed to selectedColor, and isPainted has been changed to colorClass)
import React, { useState } from 'react';
import styled, { css, ThemeProps } from 'styled-components';
const CellContent = styled.div<{ selectedColor?: string; size?: string, theme?: ThemeProps<{ background?: string; primary?: string; selected?: string }> }>`
width: ${({ size }) => size || '1vmin'};
height: ${({ size }) => size || '1vmin'};
border: thin solid white;
background-color: ${({ theme }) => theme.primary || 'lightgrey'};
&:hover {
background-color: ${({ selectedColor }) => selectedColor } ;
}
&.red {
background-color: red;
}
&.blue {
background-color: blue;
}
`;
interface CellProps {
selectedColor: string;
painting: boolean;
setPainting: React.Dispatch<React.SetStateAction<boolean>>;
}
const Cell = ({ selectedColor, painting, setPainting }: CellProps) => {
const [colorClass, setColorClass] = useState('')
const onMouseDown = () => setPainting(true);
const onMouseUp = () => setPainting(false);;
const onClick = () => setColorClass(selectedColor);
const onMouseOver = () => {
if (painting) {
setColorClass(selectedColor);
}
}
return <CellContent {...{selectedColor, className: colorClass, onClick, onMouseOver, onMouseDown, onMouseUp}} />
}

How state of a react hook must update if it has Map?

I have multiple(more than 15) div tags as tiles. I need to emphasis each one if mouse hover on it. So each tag has onMouseEnter/Leave functions as bellow.
<div
key={key}
onMouseEnter={onMouseEnter(key)}
onMouseLeave={onMouseLeave(key)}
>
...
</div>
Also I put each tiles key in a Map data structure.
const onMouseEnter = key => {
return function() {
const newIsHover = new Map(isHover)
newIsHover.set(key, true)
setIsHover(newIsHover)
}
}
const onMouseLeave = key => {
return function() {
const newIsHover = new Map(isHover)
newIsHover.delete(key)
setIsHover(newIsHover)
}
}
Since component is hook it put its state in a useState.
const [isHover, setIsHover] = useState(new Map())
What is happening here:
Always I enter a tile: onMouseEnter function called and its key added to map (as expected)
When I leave a tile: always onMouseLeave called but sometimes key is removed (as expected) and tile turned back to its normal shape but sometimes it does not(problem is here, in this situation map updated at setIsHover in onMouseLeave but it does not changed in the component!).
I think map updated as expected but when I move on new tile it does not understand that yet. So it overwrite it with what it has.
PS: example added. Move between tiles with high speed!
Like the class-based components, calls to update state are asynchronous and get queued up. Try using functional state updates to ensure these queued-up updates correctly update the previous state. This should fix race conditions between quick successive setIsHover calls with the same key.
Notice if you move slowly enough between tiles they correctly highlight and unhighlight, but more quickly (like a swipe) and 2 or more can get stuck until you again slowly exit the tile.
const onMouseEnter = key => {
return function() {
setIsHover(prevIsHover => {
const newIsHover = new Map(prevIsHover);
newIsHover.set(key, true);
return newIsHover;
});
}
}
const onMouseLeave = key => {
return function() {
setIsHover(prevIsHover => {
const newIsHover = new Map(prevIsHover);
newIsHover.delete(key);
return newIsHover;
});
}
}
But I should note that this is a lot of leg work for simply applying some component styling, especially hovering. It could more simply be achieved using CSS.
tileStyles.css
.tile {
background-color: lightgray;
border: 3px solid black;
height: 100px;
line-height: 100px;
margin: 10px;
text-align: center;
width: 100px;
}
.tile:hover {
border-color: red;
}
tile.jsx
import React from "react";
import { withStyles } from "#material-ui/core";
import "./tileStyles.css";
const styles = {
container: { display: "flex", width: "600px", flexWrap: "wrap" }
};
const Tiles = ({ classes: { container }, tiles }) => {
return (
<div className={container}>
{tiles.map((tl, key) => {
return (
<div className="tile" key={key} name={key}>
hi
</div>
);
})}
</div>
);
};
export default withStyles(styles)(Tiles);
The normal and hovered styles are applied together (at the same time) and CSS/html will manage when it hovered or not. The component no longer requires event listeners and doesn't need to maintain internal state.
Explanation
what means "...calls to update state are asynchronous and get queued up."?
When you call this.setState or a useState update function the update doesn't happen synchronously right then and there, but they are queued up during the current render cycle and batch processed in the order in which they were queued. Perhaps this demo will help illustrate what happens. What confounds this issue is the fact that event processing is also asynchronous, meaning that, when events occur their registered callbacks are placed in the event queue to be processed.

Set dynamic style for Checkbox in Ant Design

Is it possible to set tick container's style backgroundColor and borderColor in Checkbox dynamically from JSX?
I can do it with CSS/LESS, but I need to set specific color based on data from API.
Example:
.
If the colors from API are completely unknown to you until the time of running, then there is no way to accomplish the task with Antd library. Because the class you need to update colors for (.ant-checkbox-checked .ant-checkbox-inner) is nested inside the parent component , and can be changed only in your .less file.
As you can see in Rafael's example, you can only control the colors of the parent (.ant-checkbox-wrapper) from .js file.
On the other hand, if you know there will always be, let's say "#1890FF", "#FA8072", and "#008100" colors, you just don't know in what order, you can easily change the colors dynamically, by creating your logic around CSS classes. Which means you can map through all your checkboxes and give the classNames based on the color you get from API (getColor function). In order to do so, in your .js file import the data from API and define getColor function:
import React, { PureComponent } from "react";
import { Checkbox } from "antd";
export default class ColoredCheckboxes extends PureComponent {
getColor = color => {
let checkboxClassName = "checkbox-green";
if (color === "#FA8072") {
checkboxClassName = "checkbox-orange"
}
if (color === "#1890FF") {
checkboxClassName = "checkbox-blue"
}
return checkboxClassName;
};
render() {
const dataFromAPI = [
{
key: "first",
name: "First",
color: "#008100",
},
{
key: "second",
name: "Second",
color: "#FA8072",
},
{
key: "third",
name: "Third",
color: "#1890FF",
},
]
return (
<div>
{dataFromAPI.map(item => (
<div key={item.key}>
<Checkbox className={this.getColor(item.color)}>
{item.name}
</Checkbox>
</div>
))}
</div>
);
}
}
Then in your .less file reassign the colors for ".ant-checkbox-checked .ant-checkbox-inner" class originally coming from Antd Library:
.checkbox-green {
.ant-checkbox-checked .ant-checkbox-inner {
background-color: #008100;
border-color: #008100;
}
}
.checkbox-orange {
.ant-checkbox-checked .ant-checkbox-inner {
background-color: #FA8072;
border-color: #FA8072;
}
}
.checkbox-blue {
.ant-checkbox-checked .ant-checkbox-inner {
background-color: #1890FF;
border-color: #1890FF;
}
}
You just styled it, something like
<Checkbox
style={{
backgroundColor: data.backgroundColor,
borderColor : data.borderColor
}}
/>

How to handle mouse event in stateless component in React

All:
I wonder if I use stateless component, how can I handle mouse event to change component style, for example:
const Com = (props) => {
var hltStyle = false;
function highlight(){
// I do not know what put here
}
var hltStyle = {
backgroundColor: !hltStyle?"lightgreen": "tomato"
}
return (
<div style={hltStyle} onMouseOver={ highlight } >HOVER ME</div>
)
}
What I want just hover this component and change background color. There is some other logic inside highlight, that is why I can not simply use CSS
Thanks
You can achieve that using something like this
const Com = () => {
function over(e){
e.target.style.backgroundColor="red";
}
function out(e){
e.target.style.backgroundColor='';
}
return <div onMouseOver={over} onMouseOut={out}>HOVER ME </div>;
}
Anyway, if you feel that you need to declare some variables to use them as the state, you should use a normal component instead of a stateless one.
jsfiddle
What about using classic CSS for simple hover effects?
<div class="el-to-hover"></div>
somewhere in css-file:
.el-t-hover {
background: transparent
transition: background .3s ease-in-out;
}
.el-to-hover:hover {
background: red
}

Resources