React ignores one of two style classes - css

Two buttons are rendered in my button component. Depending on the label, the button receives the class addButton or clearButton.
Button Component:
import './Button.css'
interface ButtonProps {
lable: string,
disabled: boolean,
onClick: MouseEventHandler<HTMLButtonElement>
}
export const Button: FunctionComponent<ButtonProps> = ({ lable, disabled, onClick}): ReactElement => {
let style: string = lable == 'ADD' ? 'addButton' : 'clearButton';
console.log(lable);
console.log(style);
return(
<div>
<button className= {`button ${style}`} type='button' disabled= { disabled } onClick= { onClick }>
{lable}
</button>
</div>
);
}
In the stylesheet Button.css are the two classes addButton and clearButton. Strangely, only the style class that is in second place is loaded. In this situation, the addButton receives its colour and the clearButton remains colourless. If I place the style class of the clearButton in second place in the stylesheet, it receives its colour and the addButton remains colourless.
Button.css
.clearButton {
background-color: #8c00ff;
}
.addButton {
background-color: #7ce0ff;
}
If I outsource both style classes to separate stylesheets, it works but this is not an elegant solution.
I would also like to understand the problem

I've execute your code, and it works, I think the problem is where you call the button you are not passing props to

change import type of button style
import styles from './Button.css';
return(
<div>
<button className={`button ${label === 'ADD' ? styles.addButton : styles.clearButton}`}>
{lable}
</button>
</div>
);
and reolace background-color to background
.clearButton {
background: #8c00ff;
}
.addButton {
background: #7ce0ff;
}
you can test code in this codesandbox project

Related

Add color on every button Click React js

Hello guys I currently have a buttons like category. I want that when I click a button it will have a color, and when I click it again it will turn to it's original color which is white. When I click 2 button both will have dark color, then click again to remove single color.
this is my div when I'm adding a the category id
<div className={classes.scrollMenu}>
{categories.map((category) => {
return (
<>
<Button
key={category._id}
className={classes.button}
onClick={(e) => {
let values = {
price: [],
category: [category._id],
}
}}
>
{category.name}
</Button>
</>
)
})}
</div>
This is the image that when I click single button it will color one button.
Thank you
code Solution: https://codesandbox.io/s/stoic-meadow-y5cei?file=/src/App.js
App.js
import "./styles.css";
import React, { useState } from "react";
export default function App() {
let categories = ["one", "two", "three"];
const [activeFilter, setActiveFilter] = useState(["one"]);
const categoryOnClick = (category) => {
activeFilter.includes(category)
? removeCategory(category)
: setCategory(category);
};
const setCategory = (category) => {
setActiveFilter([...activeFilter, category]);
};
const removeCategory = (category) => {
const index = activeFilter.findIndex((cat) => cat === category);
activeFilter.splice(index, 1);
setActiveFilter([...activeFilter]);
};
return (
<div className="chip-list my-3">
{categories.map((category, index) => {
return (
<button
key={index}
className={`${activeFilter.includes(category) ? "active" : ""}`}
onClick={() => categoryOnClick(category)}
>
<span>{category}</span>
</button>
);
})}
</div>
);
}
css
.active {
background-color: black;
color: white;
}
check if this solution works for you
used useState hook to hold the state of buttons which you will select
.active class will apply to the button which is selected
On click of that button we will check if the button is already selected or not if selected removeCategory() function run
or if button is not selected then setCategory() function will run and it will update the state
if you need clarification please let me know thanks
Few tips to start with:
Fragment is unnecessary when wrapping single DOM element
Inline function initialisation inside a render is a bad thing. On each new re-render, it allocates extra client memory to newly initialised function. That means, for every map object you will have that many functions, that gets newly created and referenced on each reload
You can easily go with single line return statement of arrow function here. () => <hi> instead of () => { return <hi> }
As for solutions, there are quite a few ways to change button colour during execution. I will suggest the most simple (in my opinion) way to do it. Just have classname variable, then add subclass that will style button accordingly.
Example:
By default it has class name of .button, after click you simply add styling and it ends up having .button .button--red, all is left to do, declaration in css.
.button {
style button here
. . .
add additional stylings here
. . .
&.button--red { color: red }
}
As for how handler should look like, if that is what you asking. Button could be used in your new component let's say, named StyledButton or ColourfulButton that will have internal state to handle what kind of colour is represented.

Material-UI styling the button variant outlined

I'm new to Material UI and I'm struggling.
I have a button component
export default function TheButton(props: PropsWithChildren<Props>) {
const { className, hover, level,...rest } = props;
const classes = useStyles();
return (
<Button
{...rest}
className={clsx(classes.root, className, hover === 'contained' && classes.hoverContained)}
>
{props.children}
</Button>
);
}
From this component, I'd like to have two variants: contained and outlined. Here is my outlined button.
<TheButton
variant="outlined"
color="secondary"
>
secondary
</TheButton>
When the variant outlined is selected the button has the class Muibutton-outlined. I'd like to override this class to change the border (only in the outlined variant, so only on this class).
So far I've tried something like:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
'.MuiButton-outlinedSecondary':{
border:"2px solid red" ,
},
}
)
It doesn't work.
I have a similar setting, and I tried:
adding a class submit to my button component
<Button
type="submit"
variant="outlined"
disabled={isSaving || invalid || unchanged}
color="secondary"
className={classes.submit}
>
SAVE CHANGES
</Button>
since I have the submit class I can be more precise in my styling like so:
const useStyles = makeStyles({
submit: {
marginTop: padding.medium,
marginLeft: padding.small,
'&.MuiButton-outlinedSecondary': {
border: '1px solid pink',
},
},
});
Here is the result:
Material-ui button with pink border image
As long as I have used Ant design ui kit and I have overrided styles on its default style like this:
<Button type="primary" className={styles.custom_css}>click</Button>
This has done in react and custom_css class overrides its styles on default
This might can help you, if not please let me know

How to change button icon when button is clicked in react.js

I have a react function which returns a button.
<div className="col-6 btn-group btn-group w-100">
<AuditMenuButtons buttonValue='Pending' buttonName='Inbox' changeFilterForButton={this.props.changeFilterForButton} icon={icon_inbox}/>
<AuditMenuButtons buttonValue='Rejected' buttonName='Rejected' changeFilterForButton={this.props.changeFilterForButton} icon={icon_rejected}/>
<AuditMenuButtons buttonValue='Accepted' buttonName='Accepted' changeFilterForButton={this.props.changeFilterForButton} icon={icon_accepted}/>
</div>
Function is added below
function AuditMenuButtons(props) {
return(
<button className="w-25 btn menu-btn p-lg-3" name={props.buttonName} value={props.buttonValue} onClick={props.changeFilterForButton}><img src={props.icon} className="pr-3 menu-btn-icons">
</img>{props.buttonName}</button>
);
}
You will see 3 buttons in above code. I want to change the button icon when one button is clicked. actually button icon color should be green when button is clicked. Images are .png file (with green and silver border). I tried button:active in css it didn't work for me. Image should remain until I clicked another button or page was refreshed
In this case, the icon part is a UI state, it has to maintained in your state and passed down to AuditMenuButtons has props.
use these props in AuditMenuButtons to do the desired check.
import React,{Component} from 'react';
class demoComponent extends from Component{
this.state={
isClicked:false,
buttonIcons:{
pending:{active_Icon:"../IconURL",Icon:"../IconURL"},
rejected:{active_Icon:"../IconURL",Icon:"../IconURL"},
accepted:{active_Icon:"../IconURL",Icon:"../IconURL"}
}
}
clickHandler = (event) =>{
this.setState(
{
isClicked:!this.state.isClicked // this is gonna toggle everytime you click //
}
);
}
render(){
return <div className="col-6 btn-group btn-group w-100">
<AuditMenuButtons clickhandler={this.clickHandler} buttonValue='Pending' buttonName='Inbox' isClicked={this.state.isClicked} buttonIcons={this.state.buttonIcons} changeFilterForButton={this.props.changeFilterForButton} icon={icon_inbox}/>
<AuditMenuButtons clickhandler={this.clickHandler} buttonValue='Rejected' buttonName='Rejected' isClicked={this.state.isClicked} buttonIcons={this.state.buttonIcons} changeFilterForButton={this.props.changeFilterForButton} icon={icon_rejected}/>
<AuditMenuButtons clickhandler={this.clickHandler} buttonValue='Accepted' buttonName='Accepted' isClicked={this.state.isClicked} buttonIcons={this.state.buttonIcons} changeFilterForButton={this.props.changeFilterForButton} icon={icon_accepted}/>
</div>
}
}
export default demoComponent;
You can try something like this in your .css file.
.button:focus{background: url('your new green image');
You can manage the image path in react state and call a method attach
it to onClick, where you use setState() and update the state.
Refer
https://reactjs.org/docs/handling-events.html
https://reactjs.org/docs/react-component.html#setstate
this.state = {
image_path: 'your image url here'
}
changeUrl = () => {
this.setState({image_path:'new path'});
}
<AuditMenuButtons onClick={this.changeUrl} src={this.state.image_path}/>
You can try with this:
changeFilterForButton: function (props) {
props.currentTarget.style.backgroundColor = '#ccc';
}
function AuditMenuButtons(props) {
return(
<button className="w-25 btn menu-btn p-lg-3" name={this.props.buttonName}
value={this.props.buttonValue} onClick={this.props.changeFilterForButton}><img src={this.props.icon} className="pr-3 menu-btn-icons">
</img>{this.props.buttonName}</button>
);
}
or if you want to use react methodology then you can use construtor like this
constructor(props) {
super(props);
this.state = {isColor: false};
// This binding is necessary to make `this` work in the callback
this.changeFilterForButton= this.changeFilterForButton.bind(this);
}
changeFilterForButton() {
this.setState(state => ({
isColor: !state.isColor
}));
}
function AuditMenuButtons(props) {
return (
<button className="w-25 btn menu-btn p-lg-3" name={props.buttonName} value={props.buttonValue} onClick={props.changeFilterForButton} style="background-color: {this.state.isColor? '#CCC' : ''} "><img src={props.icon} className="pr-3 menu-btn-icons">
</img>{props.buttonName}</button>
);
}

Dynamically Styled Button in React Native using Styled Components

A Button component is generally comprised of the Text element wrapped with a TouchableHighlight (or other touchable). I'm trying to create a Button component styled using styled-components, but am having trouble getting my style to respond dynamically to props.
Button Component
Below, I've created a Button component similar to the Adapting based on props example found in the styled-component docs.
import React from 'react';
import { Text, TouchableHighlight } from 'react-native';
import styled from 'styled-components/native';
const colors = {
accent: '#911',
highlight: '#D22',
contrast: '#FFF',
}
const Label = styled.Text`
color: ${props => !props.outline ? colors.contrast : colors.accent};
font-weight: 700;
align-self: center;
padding: 10px;
`
const ButtonContainer = styled.TouchableHighlight`
background-color: ${props => props.outline ? colors.contrast : colors.accent};
width: 80%;
margin-top: 5px;
border-color: ${colors.accent};
border-width: 2px;
`
const Button = (props) => {
return (
<ButtonContainer
onPress={props.onPress}
underlayColor={colors.highlight}
>
<Label>
{props.children}
</Label>
</ButtonContainer>
);
};
export default Button;
Button Usage
After importing it, I'm using the button like this...
<Button
outline
onPress={() => console.log('pressed')}>
Press Me!
</Button>
Expected Result
And so, I would expect my button to look like this...
Actual Result
But instead it looks like this...
What I've done to troubleshoot so far
When I inspect using react-devtools, I can see that the outline prop is being passed down to the Button component.
But the prop is not passed down to any of it's children
The Passed Props part of the docs state, "styled-components pass on all their props", but I guess not all the way down?
My Question
What do I need to change so that I can dynamically style my Button based on it's props?
Here you have:
const Button = (props) => {
return (
<ButtonContainer underlayColor={colors.highlight}>
<Label>
{props.children}
</Label>
</ButtonContainer>
);
};
If ButtonContainer was a normal React component, you wouldn't expect the props passed to Button to be automatically passed to ButtonContainer. You'll have to do <ButtonContainer underlayColor={colors.highlight} {...props} /> to do it.
Actually ButtonContainer is a normal React component, the only difference is you pre-apply some styles using an HOC.
Also if you desugar this to a React.createElement call, you can see there's no way props can be passed automatically, because a Function's arguments don't get passed automatically to the function calls inside it.
const Button = (props) => {
return React.createElement(ButtonContainer, { underlayColor: colors.highlight }, ...);
};
It's nothing specific to styled-components. You just have to pass down the props yourself to ButtonContainer, as well as to Label.
So you'd rewrite your code to:
const Button = (props) => {
return (
<ButtonContainer underlayColor={colors.highlight} onPress={props.onPress} outline={props.outline}>
<Label outline={props.outline}>
{props.children}
</Label>
</ButtonContainer>
);
};
Technically a React component can pass down props to it's children, so ButtonContainer could pass them down to Label using React.Children and React.cloneElement APIs. But ButtonContainer doesn't do that for obvious reasons, e.g. you'd not want underlayColor and onPress to be passed to Label automatically. It would cause a lot of confusing bugs.

Get font color of ReactJS element

I have a React component, a button, and I need to set the background-color of a child element to the color of the button. I know that you're not supposed to call this.refs.myElement.getDOMNode() in the render() function, so I'm not sure how I'm supposed to lay this out.
At the moment, my code looks like this:
import React from 'react';
import { Button, Glyphicon } from 'react-bootstrap';
import classnames from 'classnames';
export default class GlyphButton extends Button {
constructor(props) {
super(props);
}
render() {
let {
glyph,
className,
children,
...props
} = this.props;
return (
<Button ref='btn' {...props} className={classnames([className, 'glyph-button'])}>
<Glyphicon glyph={glyph} />
{children}
</Button>
);
}
}
I need to do something like this:
let color = this.refs.btn.style.color;
return (
<Button ref='btn' ...>
<Glyphicon glyph={glyph} style={{backgroundColor: color}} />
{children}
</Button>
);
Unfortunately, this.refs hasn't been populated yet.
In case you're curious, the reason I'm doing this is because I'm using Glyphicon's free version PNGs for some icons, which are all black on a transparent background, and I'm using:
glyphicon.glyphicon-playing-dice:before {
content: "";
width: 20px;
height: 20px;
-webkit-mask-size: 100%;
-webkit-mask-image: url(/img/glyphicons/glyphicons-playing-dice.png);
display: block;
}
to make it act like a font icon. This class will make the element's background-color the color of the displayed icon.
You can set color as a state and change it in componentDidMount stage.
getInitialState: function(){
return {bgColor: ''}
},
componentDidMount: function(){
var color = React.findDOMNode(this.refs.btn).style.color;
this.setState({bgColor : color});
}
Because React recommend us that :
your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy.

Resources