I have the following code to style a button based off of a select box:
const buttonStyles = {
backgroundColor: buttonStyle === 'Black' ? colors.interactiveForegroundSecondary : buttonStyle === 'Green' ? colors.backgroundInverseSecondary : buttonStyle === 'White' ? colors.backgroundPrimary : buttonStyle === 'Lime Green' ? colors.graphTertiary : '',
color: buttonStyle === 'Black' ? colors.textInversePrimary : buttonStyle === 'Green' ? colors.textInversePrimary : buttonStyle === 'White' ? colors.interactiveForegroundSecondary : buttonStyle === 'Lime Green' ? colors.backgroundInverseSecondary : '',
"&:hover": {
background: buttonStyle === 'Black' ? colors.backgroundInversePrimary : buttonStyle === 'Green' ? colors.accentPrimary : buttonStyle === 'White' ? colors.errorBackground : buttonStyle === 'Lime Green' ? colors.backgroundInverseSecondary : '',
color: buttonStyle === 'Lime Green' ? colors.graphTertiary : ''
},
} as CrateStyleObject
And I am trying to refactor this into an Enum map in typescript like so:
enum ButtonBackground {
Black = colors.interactiveForegroundSecondary,
Green = colors.backgroundInverseSecondary,
White = colors.backgroundPrimary,
Lime Green = colors.graphTertiary ,
}
const submitBackground = (Object.keys(ButtonBackground) as (keyof typeof ButtonBackground)[]).map(
(key, index) => {
console.log(key);
return ButtonBackground[key] + index;
},
);
then setting it here on the component:
<Button
style={
buttonStyles
}
type="submit">
{text}
</Button/>
But I am having trouble assigning colors.interactiveForegroundSecondary to one of the keys since it is not a string.
Also the background color and color of the button needs to change based off of the selected value – would I have to create a separate Enum for each of the Background Color/Text Color as well as the Hover Background Color / Text Color?
I think that it would be convenient to create a separate enum for ButtonBackgroundColor, ButtonColor, ButtonBackgroundColorOnHover and ButtonColorOnHover.
I'm not sure though why are you trying to iterate over the enum when you actually want to set the buttonStyles according only to the value of the buttonStyle variable. I would go about it like this:
const buttonStyle = 'Lime Green' // For example
// You'll need to remove whitespace because enums cannot have two words
const buttonStyleWithNoWhitespace = buttonStyle.replace(/\s/g, '')
enum ButtonBackground {
Black = colors.interactiveForegroundSecondary,
Green = colors.backgroundInverseSecondary,
White = colors.backgroundPrimary,
LimeGreen = colors.graphTertiary,
}
enum ButtonColor {
Black = colors.backgroundInversePrimary,
Green = colors.accentPrimary,
White = colors.errorBackground,
LimeGreen = colors.backgroundInverseSecondary,
}
enum ButtonBackgroundOnHover {
Black = colors.backgroundInversePrimary,
Green = colors.accentPrimary,
White = colors.errorBackground,
LimeGreen = colors.backgroundInverseSecondary,
}
enum ButtonColorOnHover {
Black = '',
Green = '',
White = '',
LimeGreen = colors.graphTertiary,
}
const buttonStyles = {
backgroundColor: ButtonBackground[buttonStyle as keyof typeof ButtonBackground],
color: ButtonColor[buttonStyle as keyof typeof ButtonColor],
"&:hover": {
background: ButtonBackgroundOnHover[buttonStyle as keyof typeof ButtonBackgroundOnHover],
color: ButtonColorOnHover[buttonStyle as keyof typeof ButtonColorOnHover]
}
} as CreateStyleObject
<Button
style={buttonStyles}
type="submit">
{text}
</Button/>
The as keyof typeof Enum makes the usage of enums a bit too much when you can use a simple object for each of them, but perhaps there are other specific reasons that makes using enums necessary.
Related
I toggle between components on button click and I want to show active button when the user has clicked on a button. So backgroundColor of a clicked button should be green, but now when I click on one of the buttons, both buttons became green. How can I solve that so only one active button is green?
#customElement('my-comp')
export class myComp extends LitElement {
static styles = css`
.buttons-container {
display: inline-flex;
width: 100%;
margin: 20px;
gap: 20px;
}
button:active {
background: green;
}
`
#property() toggleComponent: boolean
constructor() {
super();
this.toggleComponent = false;
}
private toggleComponentFunc() {
this.toggleComponent = !this.toggleComponent
}
render() {
const styles = {
backgroundColor: this.toggleComponent ? 'lightgreen' : 'red',
};
const view = this.toggleComponent ?
html`<comp-a></comp-a>` : html`<comp-b></comp-b>`
return html`
<div class="buttons-container">
<button class="button" style=${styleMap(styles)} #click=${() => {this.toggleComponent = false;}}>
comp A
</button>
<button class="button" style=${styleMap(styles)} #click=${() => {this.toggleComponent = true;}}>
comp B
</button>
</div>
${view}
`;
}
}
This is the source question: What is the best way to toggle between two different Lit components?
The issue is that both buttons are being passed the same styles.
const styles = {
backgroundColor: this.toggleComponent ? 'lightgreen' : 'red',
};
If this.toggleComponent is true, styles will contain: background-color: 'lightgreen';, and then both buttons appear lightgreen.
A potential solution is to define the two style variants for the two buttons and pass them to the two buttons. Maybe something like:
// In render method (only showing changes)
const stylesBtn1 = {
backgroundColor: this.toggleComponent ? 'lightgreen' : 'red',
};
const stylesBtn2 = {
backgroundColor: !this.toggleComponent ? 'lightgreen' : 'red',
};
return html`
<button class="button" style=${styleMap(stylesBtn1)}>
comp A
</button>
<button class="button" style=${styleMap(stylesBtn2)}>
comp B
</button>
`;
Note that styleBtn1 uses this.toggleComponent and styleBtn2 uses !this.toggleComponent.
How can I get the value of oneHundredColorLevel from the array and render it outside the container of the other colors? Each set of colors should be the boxes for each color, with a separate box for the 100 level color.
Link to codepen
const colorPalette = {
Dark10: "#FEF9E8",
Dark20: "#FDF4DE",
Dark30: "#FCEFCC",
Dark40: "#F7E0A2",
Dark50: "#F0CC72",
Dark60: "#D5B363",
Dark70: "#C7A55E",
Dark80: "#B39553",
Dark90: "#9D8240",
Dark100: "#89723E",
Dark110: "#7C6737",
Dark120: "#715E32",
Dark130: "#66552E",
Dark140: "#5B4A28"
};
const ColorSwatches = ({ colors, shade }) => {
let filtered = Object.fromEntries(
Object.entries(colors).filter(([key, value]) => key.includes(shade))
);
let onehundredcolor = [];
return (
<div class="wrapper">
<div class="bigNumber">
<h1>{onehundredcolor}</h1><----SHOULD BE NAME ONLY
<p>{onehundredcolor}</p><----SHOULD BE HEX VALUE ONLY
</div>
{Object.entries(filtered).map((color, i) => {
if (i === 9) {
onehundredcolor.push(color);
console.log(onehundredcolor)
}else if(i !== 9) {
return (
<div key={i} style={{ backgroundColor: `${color[1]}` }}>
<h2>{color[0]}</h2>
<p>HEX {color[1]}</p>
</div>
);
}
})
</div>
);
};
I think that an array would be a more flexible container here than an object whose properties are the various shade/color pairs. For example:
const colors = [
{shade: 'dark', color: '#FEF9E8'},
{shade: 'dark', color: '#FDF4DE'},
...
{shade: 'light', color: '#111111'},
{shade: 'light', color: '#111122'},
...
];
Then you can filter/map as you see fit, for example:
const darkColors = colors.filter(c => c.shade === 'dark');
const lightColors = colors.filter(c => c.shade === 'light');
And you can easily access the 10th dark color via:
darkColors[9]
How can I change the css styles using JavaScript on React ?
For example I would make this:
document.querySelector('.container').style.backGroundColor='purple';
}
Is it right ? Or should i make it with another way ?
You can use the style attribute.
<SomeComponent style={{
backgroundColor: someCondition ? 'purple' : null
}} />
Considering paragraph element
document.getElementsByClassName("container").style.color = "blue";
The simple way to change css in Reactjs is Inline styling. Others way you can see at: https://codeburst.io/4-four-ways-to-style-react-components-ac6f323da822
Let example. If your want change color of user status. Active will be green or deactive will be red.
const Example = (props) => {
let isActive = Math.floor(Math.random() * 2) % 2 === 0;
const color = isActive ? 'green' : 'red';
return <div style={{backgroundColor: color}}> {isActive ? 'Active' : 'Deactive'} </div>;
}
OR:
const Example = (props) => {
let isActive = Math.floor(Math.random() * 2) % 2 === 0;
return <div style={{backgroundColor: isActive ? 'green' : 'red'}}> {isActive ? 'Active' : 'Deactive'} </div>;
}
OR all styling:
const Example = (props) => {
let isActive = Math.floor(Math.random() * 2) % 2 === 0;
let styleStatus = isActive ?
{
backgroundColor: 'green',
fontSize: '20',
} :
{
backgroundColor: 'red',
fontSize: '15',
};
return <div style={styleStatus}> {isActive ? 'Active' : 'Deactive'} </div>;
}
make a const type obj like this(must create inside render method)
const mystyle = {
color: "white",
backgroundColor: "DodgerBlue",
padding: "10px",
fontFamily: "Arial"
};
and assign this into your element like this
h1 style={mystyle}>Hello Style!</h1>
const Dropdown = ({ options, selected, onSelectedChange }) => {
const [ open, setopen ] = useState(false);
const renderedOptions = options.map((option) => {
if (option.value === selected.value) {
return null;
}
return (
<div key={option.value} className="item" onClick={() => onSelectedChange(option)}>
{option.label}
</div>
);
});
return (
<div className="ui form">
<div className="field">
<label className="label">Select a color</label>
<div onClick={() => setopen(!open)} className={`ui selection dropdown ${open ? 'visible active' : ''}`}>
<i className="dropdown icon" />
<div className="text">{selected.label}</div>
<div className={`menu ${open ? 'visible transition' : ''}`}>{renderedOptions}</div>
</div>
</div>
//Here is the selected.value state (value contains string of color name
{<div style={{ color: `${selected.value}` }}>{selected.value}</div>}
</div>
);
};
export default Dropdown;
const options = [
{
label: 'The Color Red',
value: 'red'
},
{
label: 'The Color Green',
value: 'green'
},
{
label: 'The Color Blue',
value: 'blue'
}
];
How can I use the selected.value in an external CSS file?
The data in the selected.value is a string of color name(s).
You can probably use Styled Components if that's what you're looking for, just an example, not really well thought out. The component can be in another file
const HoveredLink = styled.span`
color: ${props => props.selected ? 'black' : 'rgb(150, 153, 156)'};
`
<HoveredLink selected={\\someconditionhere} > Hover me <HoveredLink/>
You can simple use as a variable, this is not exactly CSS. So this one should work:
<div style={{color: selected.value}} >{ selected.label } </div>
You can also set style as a new variable:
const Dropdown = ({options,...}) => {
const styleDiv = {
color: options.value
}
//...
return (
//...
<div style={styleDiv}> {options.label} </div>
)
}
Here is how I solved it by using concept from this URL
import styles from './colorchange.css';
//...
//For setting default value (and closing dropdown when clicked outside)
useEffect(() => {
document.body.addEventListener('click', (event) => {
if (ref.current.contains(event.target)) {
return;
}
setopen(false);
});
document.documentElement.style.setProperty(`--variablename`, selected.value);
}, []);
//...
//inside renderedoption
return (
<div
key={option.value}
className="item"
onClick={() => {
onSelectedChange(option);
document.documentElement.style.setProperty(`--variablename`, option.value);
}}
>
{option.label}
</div>
);
//....
//for printing the color
<div className="colorcolor">This text is: {selected.value}</div>
CSS FILE:
{
--variablename: default;
}
.colorcolor {
color: var(--variablename);
}
Another way using CSS stylesheet.
Usually when I need to pass a value to use it for CSS I'll
go for specific CSS classes as I rather use the stylesheet
for style ( !== style within component ) for scalability reasons &
ease to access. If it can help ...
I. Known values case / no need to convert into word
to expect ( seems like it should be either [ blue,red,green ])
<div className = { selected.value } />
II. Need to convert into word
Let's say you need to change a selected.value that could be an hexadecimal value, you'll need to associate a word className you could use for CSS later on.
This is just an example and you can do a lot more within the expression passed
// convert anticipated value to the word you need
const colors = {'#F00': 'red', '#0F0' : green, '#00F': 'blue'};
<div className = { colors[ selected.value ] } />
📌Applied example
import './style.css' // style.css as same level of your component
const Dropdown = ({options,...}) => {
// if need to make wording *(cf:. case )
// const color = {'#F00': 'red', '#0F0' : green, '#00F': 'blue'};
//...
return (
//...
// if need to make wording *(cf:. case )
// <div className = { colors[ selected.value ] }> { selected.value } </div> */ }
<div className = { selected.value }> { selected.value } </div>
)
}
CSS for the above cases.
/*CSS file: style.css*/
.red { ...code... }
.green { ...code... }
.blue { ...code... }
Styled components documentation doesn't mention this case and I can't figure out the syntax.
How would I turn this styled component:
const StyledButton = styled.button`
color: red;
${props => props.disabled && css`
color: grey;
background-color: grey;
`}
`
into object notation:
const StyledButton = styled.button(props => ({
color: 'red',
------
}))
I know the following would solve this question, but for my use case I need to keep the logic from the first exemple. So this won't make it for me:
const StyledButton = styled.button(props => ({
color: props.disabled ? 'grey' : 'red',
backgroundColor: props.disabled ? 'grey' : transparent,
}))
Maybe this would be what you're after (or similar)
const StyledButton = styled.button((props) => {
const disabledStyles = {
color: 'grey',
'background-color': 'grey',
};
return {
color: 'red',
...(props.disabled && disabledStyles)
};
})
I definitely don't understand why you can't use the ternary approach you have above but I've had some weird reqs on projects too. Good luck