I need to take some button styling and apply it to some inline styling.
I thought this would be a simple copy and paste but when I try that I have a whole host of errors.
I've tried to convert the styles to inline format but I keep chasing errors I don't know how to resolve.
Thanks for the help.
The following is the button I am trying to apply styling to.
<BtnWrap>
{navToPage && navToPage.startsWith("/") ? (
//if it is linked to another page use router link
<LinkR to={navToPage} style={{}}>
{navToPage}
</LinkR>
) : (
//else use the smart link component
<Button
to={navToPage}
smooth={true}
duration={500}
spy={true}
exact="true"
offset={-80}
primary={primary ? 1 : 0}
dark={dark ? 1 : 0}
dark2={dark2 ? 1 : 0}
>
{buttonLabel}
</Button>
)}
</BtnWrap>
This is the button styling I am trying to convert to inline styling.
export const Button = styled(Link)`
border-radius: 50px;
background: ${({ primary }) => (primary ? "#ca1f27" : "#010606")};
white-space: nowrap;
padding: ${({ big }) => (big ? "14px 48px" : "12px 30px")};
color: ${({ dark }) => (dark ? "#010606" : "#fff")};
font-size: ${({ fontBig }) => (fontBig ? "20px" : "16px")};
outline: none;
border: none;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.2s ease-in-out;
&:hover {
transition: all 0.2s ease-in-out;
background: ${({ primary }) => (primary ? "#fff" : "#ca1f27")};
}
`;
Styles in React.js are a kind of object that is passed inside the style property like this
style={{ marginTop: 10, backgroundColor: 'red' }}
I leave some references that can help you:
https://www.w3schools.com/react/react_css.asp
https://www.pluralsight.com/guides/inline-styling-with-react
Related
Styled components has a helper css function. But I don't understand when should I used it.
For example this is their example where they use it:
import styled, { css } from 'styled-components'
const complexMixin = css`
color: ${props => (props.whiteColor ? 'white' : 'black')};
`
const StyledComp = styled.div`
/* This is an example of a nested interpolation */
${props => (props.complex ? complexMixin : 'color: blue;')};
`
But if we take similar example from docs here they don't use it:
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
Their description is also not clear and is confusing me:
A helper function to generate CSS from a template literal with
interpolations. You need to use this if you return a template literal
with functions inside an interpolation due to how tagged template
literals work in JavaScript.
Can someone help explain why we need it?
PS this answer also doesn't use it
I use the css function when I create variants for a component:
that is variant switcher:
const sizeVariant: Record<NonNullable<StyledLogoProps['size']>, ReturnType<typeof css>> = {
small: css`
width: 44px;
height: 44px;
`,
regular: css`
width: 93px;
height: 93px;
`,
};
that is component was created by 'styled-components':
interface StyledLogoProps {
size: 'small' | 'regular';
}
export const StyledLogo = styled.div<StyledLogoProps>`
${({ size }) => sizeVariant[size]}
`;
and this is the use in the react:
<>
<StyledLogo size="regular" />
<StyledLogo size="small" />
</>
quite a useful thing
I came across the error in styled-components :
Over 200 classes were generated for component......
and did the suggested fix from console, and that did the trick, but when I have a container component "Card" that when hovered should change text color of another component "Number" (which has that suggested fix applied, then I cant change the color (i assume because style overrides the hover change, because it works fine with opacity)
the mentioned components are in src/ProgressPieCard (first 2 components)
anyone got any got suggestions, thanks in advance :)
( sorry styling/position is a bit off )
CodeSandBox
const Number = styled.p.attrs<ColorProps>((props) => ({
style: {
color: props.color,
},
}))`
position: absolute;
span {
font-size: 1.5rem;
}
`;
const Card = styled.div.attrs<ColorProps>((props) => ({
style: {
background: props.color,
},
}))`
position: relative;
&:hover {
${Number} {
opacity: 0.5;
// color: red; <-- this dont work
}
}
`;
Values from props were pass as inline styles. They have higher priority. I suggest passing values from props differently. The example below will now work as you wanted.
const Number = styled.p<ColorProps>`
position: absolute;
color: ${p => p.color};
span {
font-size: 1.5rem;
}
`;
const Card = styled.div<ColorProps>`
position: relative;
background: ${p => p.color};
&:hover ${Number} {
opacity: 0.5;
color: red; <-- this WILL work :)
}
`;
I am trying to conditonally render in styled-components. This code seems to work in this case.
background-color: ${props => (props.active ? 'Black' : 'Green')};
I want to rather use object properties from a JSON file and provide 2 colours to the above condition. Something similar to these below instead of Black and Green.
${colors['Brand/PrimaryBlack']}
${colors['Brand/PrimaryGreen']}
colored.json
{
"colors": {
"Brand/PrimaryBlack": "#424449",
"Brand/PrimaryGreen": "#8ED6C9",
}
}
styles.js
import styled from 'styled-components'
import { colors } from './colored.json'
const Tabs = styled.button`
background-color: ${props => (props.active ? 'Black' : 'Green')};
`
How can I achieve this?
The ternary works exactly the same as your previous code, but just references the keys in your colors JSON, i.e. background-color: ${props => colors[props.active ? "Brand/PrimaryBlack" : "Brand/PrimaryGreen"]};.
{
"colors": {
"Brand/PrimaryBlack": "#424449",
"Brand/PrimaryGreen": "#8ED6C9",
}
}
import styled from 'styled-components'
import { colors } from './colored.json'
const Tabs = styled.button`
background-color: ${props => colors[props.active ? "Brand/PrimaryBlack" : "Brand/PrimaryGreen"]};
`;
You can do what you desire using styled components in the following way:
background-color: ${(props) =>
props.active ? colors["Brand/PrimaryGreen"] : colors["Brand/PrimaryBlack"]};
Find the working CodeSandBox here
Inside of Template literal you pass any valid JavaScript code inside of ${} expression even call to function so if you have an object which you want to access some keys you can just access those keys as you would do in a normal JavaScript code. so if you have an object colors with some properties you can access it inside of you Styled Component like this
const colors = {
"Brand/PrimaryGreen": "green",
"Brand/PrimaryBlack": "black"
};
const Comp = styled.div`
background: ${props => props.active? colors["Brand/PrimaryBlack"] : colors["Brand/PrimaryGreen"]};
color: #fff;
`;
You can simply do this
<TagName active={this.state.active}>Test</TagName>
And in your styles something like this:
const TagName = styled.button`
width: 100%;
outline: 0;
border: 0;
height: 100%;
justify-content: center;
align-items: center;
line-height: 0.2;
${({ active }) => active && `
background: blue;
`}
`;
I am migrating my app from SPA React to Next.js
I have found this weird bug wherein the SPA I have max-width: 100% while in Next.js width: fit-content
I cannot understand where the different behavior is coming from, I know I can fix it easily but I would like to understand the causes.
code is
const RadioButtonWrapper = styled.div`
color: ${({ theme, dark }) => theme.global.colors[dark ? 'white' : 'black']};
svg {
transform: scale(1.5);
fill: ${({ theme, dark }) => theme.global.colors[dark ? 'white' : 'black']};
}
[class^="StyledRadioButton__StyledRadioButtonContainer"] {
margin-bottom: 6px;
}
[class^="StyledBox__StyledBoxGap"] {
height: 0;
}
[class^="StyledRadioButton__StyledRadioButtonBox"] {
height: 18px;
width: 18px;
transition: opacity 200ms ease-in-out;
border-width: 1px;
border-color: ${({ theme, dark }) => theme.global.colors[dark ? 'white' : 'black']};
margin-bottom: 1px;
}
&:hover {
[class^="StyledRadioButton__StyledRadioButtonBox"] {
border-color: ${({ theme, dark }) => theme.global.colors[dark ? 'white' : 'black']} !important;
}
}
label {
[class^="StyledRadioButton"] {
flex-shrink: 0;
}
}
${({ rightAlign }) => rightAlign
&& ` label {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
}`}
`;
const RadioButtonGroup = ({ dark, rightAlign, ...props }) => (
<RadioButtonWrapper dark={dark} rightAlign={rightAlign}>
<GrommetRadioButtonGroup {...props} />
</RadioButtonWrapper>
);
SPA
Next.js
The difference has to do with what sort of polyfills the two compilers are using to make sure that your code can run in most browsers.
Check out the Browser Compatibility for the two properties. max-width has been part of the CSS spec for a very long time and is supported by every browser. Whereas fit-content is not supported at all in Internet Explorer and needs a prefix for Firefox.
The “max-width: 100%” version is more versatile, so your SPA ships that version.
Next.JS has more advanced polyfill techniques. They only ship the backwards compatible version to older browsers which need it. When you run your code in a modern browser you see “width: fit-content”. If you were to run the code in IE you would see “max-width: 100%” instead.
I want to use Ant design's autocomplete functionality, however I dont want to be limited to their input field look. So I want to style it however I want. Can i do that?
My custom input field
const FormInput = styled.input`
background-color: ${(props) =>
props.top ? "rgba(122,161,240, 0.3)" : "#EDEDED"};
font-size: 14pt;
font-family: var(--san-serif-2);
font-weight: 300;
padding: ${(props) =>
props.percent ? "10px 10px 10px 50px" : "10px 20px 10px 40px"};
border-radius: 10px;
outline: none;
border: none;
transition: 0.2s ease-in-out;
width: 100%;
&:hover {
background-color: ${(props) =>
props.top ? "rgba(122,161,240, 0.4)" : "#E4E4E4"};
}
&::placeholder {
color: rgba(122, 161, 240, 1);
}
`;
The Autocomplete i want to style
<AutoComplete
allowClear
value={symbol}
options={options}
style={{
width: 200,
}}
onSelect={onSelect)
onSearch={onSearch}
onChange={onChange}
placeholder="control mode"
/>
It seems like the actual input field is surrounded by a div and thats why stuff like width works. However when i do padding and other stuff, the div is the one affected and not the input field inside it.
You can do it by adding your styled input as a child of AutoComplete :
<AutoComplete
allowClear
value={symbol}
options={options}
onSelect={onSelect)
onSearch={onSearch}
onChange={onChange}
placeholder="control mode">
<FormInput />
</AutoComplete>