Set dynamic style for Checkbox in Ant Design - reactjs

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
}}
/>

Related

Material UI Stepper 4 Different Connector Color at 4 different steps

I was wondering if it was possible to have multiple connector colors with a different one at each step. So the first connector would be blue the one after that would be green then yellow then red all while keeping the previous color the same. The closest have gotten changes all previous colors to the same color. Is there a way to keep the previous the same color?
The Example I linked only has connectors of one color
Example of Stepper with Connector only one color
This answer shows how to change the color of individual StepIcons
Given that you have a function outside the component rendering the Stepper that returns an array containing the step labels and their corresponding icon color:
function getStepLabels() {
return [
{
label: "Select campaign settings",
color: "red"
},
{
label: "Create an ad group",
color: "blue"
},
{
label: "Create an ad",
color: "green"
}
];
}
you can generate classes for each label icon using material-ui's Hook API via the makeStyles function (if you are using a class component you might want to take a look at the withStyles function):
const useIconStyles = makeStyles(
(() => {
return getStepLabels().reduce((styles, step, index) => {
styles[index] = { color: `${step.color} !important` };
return styles;
}, {});
})()
);
and add the generated hook to your component: const iconClasses = useIconStyles();
When rendering the stepper you can make use of the generated classes like this:
[...]
<Step key={label} {...stepProps}>
<StepLabel
{...labelProps}
StepIconProps={{ classes: { root: iconClasses[index] } }}
>
{label}
</StepLabel>
</Step>
[...]
Here is a working example:
If you take a closer look at the render output of the Stepper component you will notice that StepLabel and StepConnector are sibling components. This means you can select a specific connector with the CSS :nth-child() pseudo-class. If you want to select the connector after the first step's label you would use the selector :nth-child(2). For the connector after second step's label it would be :nth-child(4).
If you have an array of step labels like this:
[
{
label: "First label",
connectorColor: "red"
},
{
label: "Second label",
connectorColor: "green"
},
{
label: "Third label"
}
];
you can pass this array to a material-ui style hook created by the makeStyles function and dynamically generate all the different CSS selectors necessary to style each connector:
const useConnectorStyles = makeStyles({
stepConnector: steps => {
const styles = {};
steps.forEach(({ connectorColor }, index) => {
if (index < steps.length - 1) {
styles[`&:nth-child(${2 * index + 2})`] = { color: connectorColor };
}
});
return styles;
},
stepConnectorLine: {
borderColor: "currentColor"
}
});
Now use the generated style hook in your component: const connectorClasses = useConnectorStyles(stepLabels); and provide the connector prop to the Stepper component:
connector={
<StepConnector
classes={{
root: connectorClasses.stepConnector,
line: connectorClasses.stepConnectorLine
}}
/>
}
Here is a working example:

Possible to change font color on react-select?

I have a button that when clicked, all the content is transparent.
Is it possible to manually set the text color ? Not background color !
I want black color on my font not transparent.
My Code:
import React from 'react';
import DatePicker from "react-datepicker";
import Select from 'react-select';
import "react-datepicker/dist/react-datepicker.css";
import 'react-datepicker/dist/react-datepicker-cssmodules.css';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
];
class Test extends React.Component {
state = {
startDate: new Date(),
selectedOption: null,
}
constructor() {
super();
this.state = {
};
}
handleChange = date => {
this.setState({
startDate: date
});
};
handleChange = selectedOption => {
this.setState({ selectedOption });
console.log(`Option selected:`, selectedOption);
};
render() {
const { selectedOption } = this.state;
return (
<div className="grid-container">
<DatePicker
selected={this.state.startDate}
onChange={this.handleChange}
dateFormat="yyyy-MM-dd"
/>
<Select
value={selectedOption}
onChange={this.handleChange}
options={options}
/>
</div>
);
}
}
export default Test;
I tried to manually adjust the colors through this link But without success !
I want the data to be in black letters on a white background when I click the button.
react-select is built in a way you should use CSS-in-JS and not css like describe here: https://react-select.com/styles.
Then you will be able to use some styling props like:
const customStyles = {
option: provided => ({
...provided,
color: 'black'
}),
control: provided => ({
...provided,
color: 'black'
}),
singleValue: provided => ({
...provided,
color: 'black'
})
}
And so on.
react-select v5.2.2 gives the following style keys which we can use to style different parts of UI using css
clearIndicator
container
control
dropdownIndicator
group
groupHeading
indicatorsContainer
indicatorSeparator
input
loadingIndicator
loadingMessage
menu
menuList
menuPortal
multiValue
multiValueLabel
multiValueRemove
noOptionsMessage
option
placeholder
singleValue
valueContainer
Now lets say you want to change the font color of selected option (see the img below)
now what you have to do is you need to find the right **style key** from above and
write a custom css function that's all.
you can use dev tools to inspect elements and easily find the style keys!
const customStyles = {
singleValue:(provided:any) => ({
...provided,
height:'100%',
color:'#08699B',
paddingTop:'3px',
}),
}
<ReactSelect
styles={customStyles}
/>
It took me some time to figure this out, hope it helps you and save your time to understand this.
You can find the class you want to target this way: in the browser element inspector find the element and find its class. You can that modify its class by adding:
.putElementClassNameHere {
color: black !important;
}
You might need !important for the style to be applied.

Material UI: affect children based on class

What I am trying to achieve
I have two classes - root and button - I want to affect button class on root state (for example :hover).
My attempt
I'm trying to display button on root:hover.
const styles = {
root: {
'&:hover' {
// here I can style `.root:hover`
button: {
// and I've tried to affect `.root:hover .button` here
display: 'block'
}
}
},
button: {
display: 'none'
}
}
Expected ouput:
.element-root-35 .element-button-36:hover {
display: block;
}
Current output:
.element-root-35:hover {
button: [object Object];
}
Environment
I'm using Material-UI with React.js. In this situation I'm using withStyles() export.
Below is the correct syntax:
const styles = {
root: {
"&:hover $button": {
display: "block"
}
},
button: {
display: "none"
}
};
Related answers and documentation:
jss-plugin-nested documentation
Using material ui createStyles
Advanced styling in material-ui

Render a component oclick of a row in react-table (https://github.com/react-tools/react-table)

I want to render a component when a row is clicked in a react-table. I know i can use a subcomponent to achieve this but that doesn't allow click on the entire row. I want the subcomponent to render when the user clicks anywhere on that row. From their github page i understand that i want to edit getTdProps but am not really able to achieve it. Also the subcomponent is form and on the save of that form i want to update that row to reflect the changes made by the user and close the form. Any help is appreciated.
import React, {Component} from 'react';
import AdomainRow from './AdomainRow'
import ReactTable from "react-table"
import AdomainForm from './AdomainForm'
import 'react-table/react-table.css'
export default class AdomianTable extends Component {
render() {
const data = [{
adomain: "Reebok1.com",
name: "Reebok",
iabCategories: ["IAB1", "IAB2", "IAB5"],
status: "PENDING",
rejectionType: "Offensive Content",
rejectionComment: "The content is offensive",
isGeneric: false,
modifiedBy: "Sourav.Prem"
},
{
adomain: "Reebok2.com",
name: "Reebok",
iabCategories: ["IAB1", "IAB2", "IAB5"],
status: "PENDING",
rejectionType: "Offensive Content",
rejectionComment: "The content is offensive",
isGeneric: false,
modifiedBy: "Sourav.Prem"
},
{
adomain: "Reebok3.com",
name: "Reebok",
iabCategories: ["IAB1", "IAB2", "IAB5"],
status: "PENDING",
rejectionType: "Offensive Content",
rejectionComment: "The content is offensive",
isGeneric: false,
modifiedBy: "Sourav.Prem"
}];
//FOR REACT TABLE TO WORK
const columns = [{
Header : 'Adomian',
accessor : 'adomain'
}, {
Header : 'Name',
accessor : 'name'
}, {
Header : 'IABCategories',
accessor : 'iabCategories',
Cell : row => <div>{row.value.join(", ")}</div>
}, {
Header : 'Status',
accessor : 'status'
}];
return (
<div>
<ReactTable
getTdProps={(state, rowInfo, column, instance) => {
return {
onClick: (e, handleOriginal) => {
<AdomainForm row={rowInfo} ></AdomainForm>
console.log('A Td Element was clicked!')
console.log('it produced this event:', e)
console.log('It was in this column:', column)
console.log('It was in this row:', rowInfo)
console.log('It was in this table instance:', instance)
// IMPORTANT! React-Table uses onClick internally to trigger
// events like expanding SubComponents and pivots.
// By default a custom 'onClick' handler will override this functionality.
// If you want to fire the original onClick handler, call the
// 'handleOriginal' function.
if (handleOriginal) {
handleOriginal()
}
}
}
}}
data={data.adomains}
columns={columns}
defaultPageSize={10}
className="footable table table-stripped toggle-arrow-tiny tablet breakpoint footable-loaded"
SubComponent = { row =>{
return (
<AdomainForm row={row} ></AdomainForm>
);
}}
/>
</div>
);
}
}
}
I ran into the same issue where I wanted the entire row to be a clickable expander as React Table calls it. What I did was simply change the dimensions of the expander to match the entire row and set a z-index ahead of the row. A caveat of this approach is that any clickable elements you have on the row itself will now be covered by a full width button. My case had display only elements in the row so this approach worked.
.rt-expandable {
position: absolute;
width: 100%;
max-width: none;
height: 63px;
z-index: 1;
}
To remove the expander icon you can simply do this:
.rt-expander:after {
display: none;
}
I found it was better to add a classname to the react table:
<AdvancedExpandReactTable
columns={[
{
Header: InventoryHeadings.PRODUCT_NAME,
accessor: 'productName',
},
]}
className="-striped -highlight available-inventory" // custom classname added here
SubComponent={({ row, nestingPath, toggleRowSubComponent }) => (
<div className={classes.tableInner}>
{/* sub component goes here... */}
</div>
)}
/>
Then modify the styles so that the columns line up
.available-inventory .-header,
.available-inventory .-filters {
margin-left: -40px;
}
And then modify these styles as Sven suggested:
.rt-tbody .rt-expandable {
cursor: pointer;
position: absolute;
width: 100% !important;
max-width: none !important;
}
.rt-expander:after{
display: none;
}

material-UI: Unable to set Color of SVG Icon inside Tab

Have the following inside a react class render():
import {blue900} from 'material-ui/styles/colors';
import {Tabs, Tab} from 'material-ui/Tabs';
import SocialPeople from 'material-ui/svg-icons/social/people';
var myClass = React.createClass({
render: function() {
return (
<Tabs>
<Tab icon={<SocialPeople color={blue900} />}/>
</Tabs>
);
}
});
The SVG icon color is ignored above, whereas it works below:
var myClass = React.createClass({
render: function() {
return (
<SocialPeople color={blue900} />
);
}
});
Can anyone explain this?
How to set icon color inside the tab element?
It seems like this is not possible at the moment without changing the library. I believe it's a bug. I had a hard time finding a solution to this. Then I just had a look at the code.
What I found out is that when an icon element is passed to Tab component, the props of the Tab component are changed including the style that you pass. So it makes a copy of the icon but with different props and styles and renders that.
if (icon && React.isValidElement(icon)) {
const iconProps = {
style: {
fontSize: 24,
color: styles.root.color,
marginBottom: label ? 5 : 0,
},
};
if (icon.type.muiName !== 'FontIcon') {
iconProps.color = styles.root.color;
}
iconElement = React.cloneElement(icon, iconProps);
}
So the color that you send is neglected and it takes color from the MuiTheme.
https://github.com/callemall/material-ui/blob/master/src/Tabs/Tab.js
Have a look at the code. Lines 5 to 25 and 110 to 126..
So you will need to change the library to get the color. Just follow these steps..
Open the file node_modules/material-ui/Tabs/Tab.js
Go to line 128 which reads
iconProps.color = styles.root.color
and replace it with this
if (icon.props) {
if (icon.props.style && icon.props.style.color) {
iconProps.color = icon.props.style.color;
} else if (icon.props.color) {
iconProps.color = icon.props.color;
} else {
iconProps.color = styles.root.color;
}
if (icon.props.hoverColor) {
iconProps.hoverColor = icon.props.hoverColor;
}
}
That's it.. Now your icon element should be something like this
<SocialPeople style={{ color: 'red' }} />

Resources