I can add some styles to the Menu component. But how can I add style to the Menu.Item component?
const LayoutHeader = styled(Menu)`
&& {
background: red;
}
`
Use this:
const LayoutHeaderItem = styled(Main.Item)`
&&&{
/* your code */
}
`;
Related
I'm using react and emotion. I need to change the style of an element according to a boolean value. The below code does not work. How can I combine multiple styles correctly?
import { css } from "#emotion/react"
const navSticky = css({
transform: "translateY(-10px)",
})
const navStyle = css({
background: "red",
})
...
<nav css={isSticky ? {...navStyle, ...navSticky} : navStyle}> </nav>
As first variant i suggest use styled component for this. Set background as base property and set transform if isSticky prop has been passed with true value.
As second variant i suggest correct your example. Use JSX Pragma with jsx function from '#emotion/react'. This allow use css prop. Docs: https://emotion.sh/docs/css-prop#jsx-pragma
// first variant
const Nav = styled.nav`
background: red;
transform: ${p => p.isSticky && "translateY(-10px)"};
`
const App = () => <Nav isSticky={true}>Some Elements</Nav>
// second variant
/** #jsx jsx */
import {jsx} from '#emotion/react'
const navSticky = {
transform: 'translateY(-10px)',
}
const navStyle = {
background: 'red',
}
const App = () => (
<nav css={{...navStyle, ...(isSticky && navSticky)}}>Some Elements</nav>
)
When using multiple styled components, the top one overrides other default props.
import { styled } from '#mui/material/styles'
import { Badge } from '#mui/material'
const Badge1 = styled(Badge)``
// this works if Badge1 is used directly: <Badge1 />
Badge1.defaultProps = {
max: Infinity
}
const Badge2 = styled(Badge1)`` // styled Badge1
// this overrides defaultProps from Badge1. Prop max: Infinity does no apply here
Badge2.defaultProps = {
variant: 'standard'
}
Badge2 has only variant: 'standard' default prop. It skips max: Infinity
How can I keep all the defaultProps from each level
When you style a component via multiple styled calls using Emotion, Emotion collapses the styling layers into a single wrapper component rather than adding an additional wrapper around the first wrapper. Emotion retains the defaultProps from the previous wrapper, but you are then overwriting that when you set Badge2.defaultProps.
You can retain any previous defaultProps with the following syntax:
Badge2.defaultProps = {
...Badge2.defaultProps,
variant: 'standard'
}
Below is an example demonstrating what happens with default props with each styled wrapping. The fix is demonstrated with StyledAgainWithDefaultRetainExisting.
import styled from "#emotion/styled";
function MyComponent({ className, ...defaults }) {
return <div className={className}>Defaults: {JSON.stringify(defaults)}</div>;
}
MyComponent.defaultProps = {
orig: true
};
const StyledMyComponent = styled(MyComponent)`
background-color: blue;
color: white;
`;
StyledMyComponent.defaultProps = {
styled: true
};
const StyledAgainNoDefaultsAdded = styled(StyledMyComponent)`
background-color: purple;
`;
const StyledAgainWithDefault = styled(StyledMyComponent)`
background-color: green;
`;
StyledAgainWithDefault.defaultProps = {
styledAgain: true
};
const StyledAgainWithDefaultRetainExisting = styled(StyledMyComponent)`
background-color: brown;
`;
StyledAgainWithDefaultRetainExisting.defaultProps = {
...StyledAgainWithDefaultRetainExisting.defaultProps,
styledAgainRetain: true
};
export default function App() {
return (
<div>
<MyComponent />
<StyledMyComponent />
<StyledAgainNoDefaultsAdded />
<StyledAgainWithDefault />
<StyledAgainWithDefaultRetainExisting />
</div>
);
}
I want to add styles to the custom component with a help of the styled-components library. I found some similar questions on StackOverflow with answers but it seems not to work for me. I do something like this:
Here is my custom component
const ComponentStyledBox = styled.div`
color: red;
`;
const ComponentStyled = () => (
<ComponentStyledBox>Component With StyledComponents</ComponentStyledBox>
);
And here I try to use my custom component and add some styles to it
const ComponentStyledWrapper = styled(ComponentStyled)`
background-color: green;
`;
export default function App() {
return (
<div>
<ComponentStyledWrapper />
</div>
);
}
As the result, I don't have a green background. Only red text. The same will be if I use instead of the styled custom component just a component with styles added via CSS in a common way. What do I do wrong?
For your convenience here is a CodeSandbox
Thanks in advance!
The problem is caused by this:
const ComponentStyled = () => (
<ComponentStyledBox>Component With StyledComponents</ComponentStyledBox>
);
You've defined a new component called ComponentStyled which is not style-able. Try this instead (in App.styles.tsx):
import { ComponentStyledBox } from "./components/ComponentStyled/ComponentStyled.styles";
export const ComponentStyledWrapper = styled(ComponentStyledBox)`
background-color: green;
`;
ComponentStyledBox is style-able, so you'll get the green background.
Edit (response to #zakharov.arthur's comment): If really do want a custom component with hard-coded children (are you sure this is what you want?), you can make your custom component style-able by exposing ComponentStyledBox's props:
// I haven't actually tried this but it should work.
const ComponentStyled = (props: Omit<Parameters<ComponentStyledBox>[0], 'children'>) =>
<ComponentStyledBox {...props}>Component With StyledComponents</ComponentStyledBox>
I'm using higher order components to reuse React/Next.js components but with different styles. However, this works only for vanilla React where pages are not generated either server-side or statically. If some pages are static and others dynamic, it won't work.
Here's an example component. We'll focus on TabStyles.Main in a little while:
const Tabs: NextPage<Props> = ({ ... }: Props) => {
...
return (
<TabStyles.Main>
...
</TabStyles.Main>
);
};
export default Tabs;
Here're its styles:
import styled from "styled-components";
const Main = styled.div`
display: flex;
flex-direction: column;
`;
...
export const TabStyles = {
Main,
...
};
Now let's implement two HOCs.
In red.tsx, rendered at path /red, color is red:
// Import Tabs and TabStyles
const TabsFontRed = <P extends {}>(Component: NextPage<P>) => {
TabStyles.Main = styled(TabStyles.Main)`
color: red;
`;
const NewComp = (props: P) => <Component {...props} />;
return NewComp;
};
const RedHOC = TabsFontRed(Tabs);
In blue.tsx, rendered at path /blue, color is blue.
// Import Tabs and TabStyles
const TabsFontBlue = <P extends {}>(Component: NextPage<P>) => {
TabStyles.Main = styled(TabStyles.Main)`
color: blue;
`;
const NewComp = (props: P) => <Component {...props} />;
return NewComp;
};
const BlueHOC = TabsFontBlue(Tabs);
This works if all pages are dynamic because TabStyles.Main = styled(TabStyles.Main)... is called every time we load the page, thus changing color to the correct one.
However, it seems if /red is static but /blue isn't, as we might do with Next.js, the behaviour will be different:
Go to /red first, font is red. Good.
Go to /blue, font is blue. Also good.
Go back to /red, font is now blue. Oh no!
Is there a way to augment this higher order component plus styled-components pattern so that styling will remain different when some pages are static and some are not?
Edit, 1 April 2021:
React complains in the console if we do this. I lost the notice now but it makes me think this is a bad idea. Probably, overriding styles is not good use of higher order components. Now I think HOCs should be used for adding logic, not styles.
Override styled-components in conventional fashion like this:
const NewStyledComp = styled(OlderStyledComp)`
background-color: ...;
`
Or like this:
const NewStyledComp = styled.div`
${OlderStyledComp} {
background-color: ...;
}
`
I am learning Styled-component: I would like my code to render a text line (Your personal trainer) but I do not want to have it in App.js file. How can I do that?
import styled from 'styled-components';
const StyledTextLine = styled('YOUR PERSONAL TRAINER')`
color:#333333 100%;
font-size: 17px;
font-family: NeuropoliticalRg-Regular;
word-spacing:0px;
`;
export default StyledTextLine;
Assuming you might want a span:
const StyledTextLine = styled.span`
color:#333333 100%;
font-size: 17px;
font-family: NeuropoliticalRg-Regular;
word-spacing:0px;
`;
const TextLine = () => {
return <StyledTextLine>YOUR PERSONAL TRAINER</StyledTextLine>
}
If you need more help with styled-component feel free to drop on their docs
If you want to re-use the component pass a prop for a message like this:
const TextLine = ({ message }) => {
return <StyledTextLine>{message}</StyledTextLine>
}