I don't know if this is possible with SCSS but I'm trying, how do I pass a react boolean variable of true to an scss mixin?
My React component,
Here I pass a variable from the react-html side to scss
type Props = {
isGrey?: boolean;
isOrange?: boolean;
};
export default function Button({ isGrey, isOrange }: Props) {
return (
<div className="button" style={{ '--isGrey': true }} >
{isGrey.toString()}
</div>
);
}
My Sass code,
Here I try to use the boolean passed from the React code in a mixin, but it doesn't work
#mixin button-style($isGrey: false) {
// #error $isGrey; // this prints "--isGrey" on screen, I need it to print true
#if $isGrey == true {
border: 2px solid #d5d5d5;
} #else {
border: 2px solid red;
}
}
.button {
#include button-style($isGrey: --isGrey);
height: 50px;
width: 100%;
border-radius: 4px;
}
Any help will be much appreciated...
Maybe I'm just oldskool, but I'd stay away from even attempting something like this and just stick with a classical way of changing the style of your elements, specifically something like a button.
I'd just have your base button style
.button {
height: 50px;
width: 100%;
border-radius: 4px;
}
Then make use of some additional classes to change the style based on the boolean.
.btn-primary {
border: 2px solid #d5d5d5;
}
.btn-secondary {
border: 2px solid red;
}
Within your component then just append the additional class based on the boolean.
return (
<div className=`button ${isGrey ? 'btn-Primary' : 'btn-Secondary'}`>
{isGrey.toString()}
</div>
);
It's cleaner and easier to read.
Related
I have this .button rule in Cta.module.scss-
.button {
$bg-color: white;
$text-color: variables.$color-text-cta;
background-color: $bg-color;
color: $text-color;
display: inline-block;
padding: variables.$padding-block-sm variables.$padding-inline-sm;
border: 0.056rem solid transparent;
border-radius: 0.278rem;
box-shadow: rgba(0, 0, 0, 0.239) 0 0.111rem 0.556rem;
#include mixins.cta-hover($bg-color, $text-color);
}
I want to override some properties for this .button class in IntroSection/index.module.scss, which I could do pretty easily if I was using styled-components; something like-
import {Button} from 'Cta/Cta.styles.js';
const Section = styled.section`
${Button} {
...
}
`;
I have no idea how (or if) we can achieve such a thing using scss modules. I tried a similar approach in index.module.scss-
#use '../../comps/Cta/Cta.module';
.section {
Cta.button {
padding: variables.$padding-block-md variables.$padding-inline-md !important;
&:first-of-type {
margin-right: variables.$margin-sm;
}
}
But it doesn't seem to work. What's the correct approach to achieve the result I want?
Below is what Cta.jsx contains in it-
import React from 'react';
import styles from './Cta.module.scss';
export default function Cta({ children, backgroundColor }) {
const classForBgColor = styles['button--' + backgroundColor];
return (
<button className={`${styles.button} ${classForBgColor || ''}`}>
{children}
</button>
);
}
MWE
https://codesandbox.io/s/slider-example-ev250?file=/src/App.js
Question
I am attempting to create an <input type='range'> Styled Component that has a custom appearance:
const SliderInput = styled.input.attrs((props) => {
const val = Number(props.value ?? 0);
const min = Number(props.min ?? 0);
const max = Number(props.max ?? 1);
const breakpoint = 100 * ((val - min) / (max - min));
return {
style: {
background: `linear-gradient(to right, ${props.color}, ${props.color} ${breakpoint}%, white ${breakpoint}%, white 100%)`,
border: `solid 1px ${props.color}`
}
};
})`
-webkit-appearance: none;
width: 200px;
height: 8px;
border-radius: 12px;
&::-webkit-slider-thumb {
-webkit-appearance: none;
background: ${(props) => props.color};
border: 2px solid white;
border-radius: 50%;
width: 16px;
height: 16px;
}
&:hover {
cursor: grab;
}
`;
The issue I am facing is that the background color of the thumb slider changes too frequently, which causes lagging and I see the following warning:
Over 200 classes were generated for component styled.input with the id of "sc-dlnjwi".
Consider using the attrs method, together with a style object for frequently changed styles.
Example:
const Component = styled.div.attrs(props => ({
style: {
background: props.background,
},
}))`width: 100%;`
How can this be achieved with pseudo-selectors like ::-webkit-slider-thumb?
I've tried:
style: {
background: `linear-gradient(to right, ${props.color}, ${props.color} ${breakpoint}%, white ${breakpoint}%, white 100%)`,
border: `solid 1px ${props.color}`
"::WebkitSliderThumb": {
background: props.color
}
}
To no avail.
Any suggestions?
It's not possible to style psuedo-selectors using inline styles (see this SO thread for more context). In other words, this isn't possible:
<input type="range" style="::WebkitSliderThumb:background:red" />
That's what styled-components's .attrs is doing under the hood, it's just applying inline styles [docs].
The only way to apply styles to psuedo-selectors is to use CSS, and as you've already seen it's not practical to do this with styled-components. I'd suggest determining a fixed number of slider steps, generating CSS classes for each of those ahead of time (you can use a preprocessor like SASS to do this effeciently), and then just dynamically applying the correct class when the slider's value changes.
I am fairly new to React and I am using styled-components.
const Button = styled.button`
height: 35px;
width: 85px;
color: #0288d1;
border: 1px solid #0288d1;
background: white;
border-radius: 1px;
&:hover {
cursor: pointer;
background: #cfe8ef;
}
&:focus {
background: #0288d1;
color: white;
}
`;
I would like to prevent the button from losing focus when the user clicks somewhere else on the screen. Would I need to add additional JavaScript code to do this or is there a CSS property that can help me with this issue?
Try below:
const setFocus = e => {
e.target && e.target.focus();
};
return (
<button
onBlur={e => {
setFocus(e);
}}
>
My Button
</button>
);
You can add :active in global stylesheet.
button:active {
border: 2px solid #000;
}
So any time, button tags receive this style in active mode.
I have a component for my button with its own css file, but I'm trying to figure out how to add a className directly to the component and change the CSS for mobile view. Right now, the Button.css file overrides everything and my new className added to the component doesn't even show up in the html.
Here is the Button.js file
import React from 'react';
import './Button.css'
const STYLES = [
'btn--primary',
'btn--outline'
]
const SIZES = [
'btn--medium',
'btn--large'
]
export const Button = ({
children,
type,
onClick,
buttonStyle,
buttonSize
}) => {
const checkButtonStyle = STYLES.includes(buttonStyle) ? buttonStyle : STYLES[0]
const checkButtonSize = SIZES.includes(buttonSize) ? buttonSize : SIZES[0]
return (
<button className={`btn ${checkButtonStyle} ${checkButtonSize}`} onClick={onClick} type={type}>
{children}
</button>
)
}
Here is the Button.css
:root {
--primary: #3acbf7;
}
.btn {
padding: 8px 20px;
border-radius: 4px;
outline: none;
border: none;
cursor: pointer;
}
.btn:hover {
background-color: transparent;
color: #fff;
padding: 8px 20px;
border-radius: 4px;
border: solid 2px var(--primary);
transition: all 0.3s ease-out;
}
.btn--primary {
background-color: var(--primary);
}
.btn--outline {
background-color: transparent;
color: #fff;
padding: 8px 20px;
border-radius: 4px;
border: solid 1px var(--primary);
transition: all 0.3s ease-out;
}
.btn--medium {
padding: 8px 20px;
border-radius: 4px;
font-size: 18px;
color: #fff;
}
.btn--large {
padding: 12px 26px;
border-radius: 4px;
font-size: 20px;
color: #fff;
}
And here is the main component where I'm trying to add a custom className to override the code above. Note this code is inside of a Navbar component.
import React, { Component } from 'react';
import { MenuItems } from "./MenuItems"
import { Button } from "../Button"
import './Navbar.css'
class Navbar extends Component {
render() {
return (
<nav className="NavbarItems">
<Button className="btn-mobile">Sign Up</Button>
</nav>
)
}
}
If I try to add .btn-mobile to my Navbar.css, none of the properties show up in the html. I tried to add an id and still didn't work. Not sure how to custom the button since it's a component with preset properties
The way that I generally accomplish this is to accept className as a prop and spread it into the default classes of the element, like so:
const Button = ({className='', text, ...rest}) => (
<button className={`my-button-class ${className}`} {...rest}>{text}</button>
)
Then you could use it like so:
<Button className="my-custom-class" text="press me" id="my-id" />
and it will render as
<button class="my-button-class my-custom-class" id="my-id">press me</button>
By defaulting the className prop to an empty string, it won't be added as the string of "undefined" if the implementation doesn't pass a className. Note that we also spread in any other props that were passed.
I want to design a dynamic nav tabs component. when the card is clicked relevant tab is shown, with the connection arrow and border-color green.
sample code or a suggestion would be much helpful
.
You can use accordion by bootstrap. Use css flexbox to horizontally align the tabs next to each other and bind a javascript method that changes css color properties (arrow, green color) on clicking.
Here is the link - https://getbootstrap.com/docs/4.0/components/collapse/
Here is how you can do :
.js :
import React, { Component } from "react";
import { render } from "react-dom";
import "./style.css";
const App = () => {
const selectBlock = (e) => {
e.target.classList.toggle('selected');
}
return (
<div className="block" onClick={(e) => {selectBlock(e)}}>
<div>Here is the block</div>
<div className="arrow">
<FakeArrow />
</div>
</div>
);
};
const FakeArrow = () => {
return (
<div>
<span className="arrow-down-border" />
<span className="arrow-down" />
</div>
);
};
render(<App />, document.getElementById("root"));
.css :
.block {
position: relative;
width: 150px;
height: 50px;
text-align: center;
border: 2px solid black;
}
.arrow {
display: none;
}
.block.selected {
border: 2px solid #99d32c;
}
.block.selected .arrow {
display: block;
}
/* You need to fake the arrow border with another arrow behind */
.arrow-down-border {
position: absolute;
bottom: -20px;
left: 55px; /* 150px (main block) / 2 -20px (size of the triangle)*/
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid #99d32c;
}
.arrow-down{
position: absolute;
bottom: -17px;
left: 58px; /* 150px (main block) / 2 -17px (size of the triangle)*/
width: 0;
height: 0;
border-left: 17px solid transparent;
border-right: 17px solid transparent;
border-top: 17px solid #ffffff;
}
Here is the repro on Stackblitz.
Of course this is just an example, you have to set a color for the arrows so my advice would be to do it with constants or props. Same thing for the position and others functionality you can add to the FakeArrow component.
Now, it would be waaaayy easier to manage it with an image if you really need a border (this is the tricky part in your requirement), or a simple arrow without border.
You can take a look at this post, it's the same question actually, i used a slightly different way to do it with css, but the result seems to be the same.