styled components: how to select child component? - javascript

// card.js
import styled from 'styled-components'
const Heading = styled.h1`
color: red;
`;
const Summary = styled.p`
text-align: center;
`;
const Card = ({className, heading, summary}) => (
<div className={className}>
<Heading>{heading}</Heading>
<Summary>{summary}</Summary>
</div>
);
export default Card;
// cardWithBlueHeading.js
import styled from 'styled-components';
import Card from './card.js';
const CardWithBlueHeading = styled(Card)`
// How can I select the Heading component and make it blue?
`;
export default CardWithBlueHeading;
I'm trying to change the styles of a child component. These styles will likely be a one off situation. I'm trying to avoid selecting the HTML element h1 and pseudo selectors.

You can pass props to styled components like below:
import styled from 'styled-components'
const Heading = styled.h1`
color: ${props => props.color};
`;
Pass the color as prop
<Heading color='blue'/>

You can give your Heading a className property and then select it with
const CardWithBlueHeading = styled(Card)`
> .[classNameYouGive] {
background: blue;
}
`;
This is the standard css way.

Related

How to extend component style in styled-components

I have a basic ElipseDetail component that looks like the image below
<ElipseDetail text="1.07" />
When I am using the component everything works as expected.
But now I want to reuse the component in another place but add an extension to the Text component style
How can I achieve that with styled-components and reuse the component but change the Text which is a child?
import React, { ReactElement } from "react";
import styled from "styled-components";
interface Props {
text: string;
children?: React.ReactNode;
}
export const Container = styled.div`
padding: 4px 12px;
border-radius: 30px;
background-color: #eaeef2;
display: inline-block;
`;
export const Text = styled.p`
font-size: 12.5px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
letter-spacing: 0.63px;
color: #687c97;
`;
export default function ElipseDetail({ text, children }: Props): ReactElement {
return (
<Container>
<Text>{text}</Text>
{children}
</Container>
);
}
Since ElipseDetails is not a styled component, but calls to a styled one, you can do something like:
function ElipseDetail({ text, children }: Props): ReactElement {
return (
<Container>
<Text>{text}</Text>
{children}
</Container>
);
}
ElipseDetail.Styled = Container;
export default ElipseDetail
And then, in a different component, you can change it like so:
const StyledElipseDetail = styled(ElipseDetail.Styled)`
${Text} {
//
}
`;
...
return <StyledElipseDetailed>...</StyledElipseDetail>
PS - I have taken this approach from an older question of mine which I found quite useful.
I would suggest to create a container and if Text is in that container then add different properties. & here means this class name so it evaluates to Text so when text would be in ElipseContainer then it will behave in different way depending on your use case. Here if it's wrapped with ElipseContainer then colour of Text is green and it's red otherwise.
Here is sandbox link :
sandobx
const ElipseContainer = styled.div``;
const Text = styled.p`
color: red;
${ElipseContainer} & {
color: green;
}
`;
const App =() =>
<ElipseContainer>
<ElipseDetail text="word2" />
</ElipseContainer>

Unable to apply styles to styled-component element in Reactjs

I'm trying to wrap a component with a styled-component div and apply some styles. However, for some reason, the styles aren't being applied, even though the ostensibly correct wrapper that is expected to be rendered is being rendred.
CodeSandbox
What am I doing wrong here?
You just forgot to pass the className props, see here:
const Component = ({ className }) => (
<div className={className}>Hello World!</div>
);
https://codesandbox.io/s/optimistic-lumiere-cq8gt?file=/src/App.js
I hope I helped you. Have a good day.
EDIT: Check the docs here
You need to container Component with styled.{tag} or styled(Component)
And then use that Container component to wrap main component.
import React from "react";
import "./styles.css";
import styled from "styled-components";
export default () => <Component />;
const Component = () => <StyledDiv>Hello World!</StyledDiv>;
const StyledDiv = styled.div`
font-size: 10rem;
color: red;
display: flex;
justify-content: center;
align-items: center;
`;
Check here: https://codesandbox.io/s/dank-hill-h8rbc?file=/src/App.js:128-189

Styled-components and react-icons <IconContext.Provider> component

i'm new to styled-components and i want to use <IconContext.Provider> from react icons this is my react component:
<myComp>
<AiFillPlusCircle />
</myComp>
and this is my styled components code:
import { IconContext } from 'react-icons';
export const myComp= styled(IconContext.Provider)`
color: rgb(71, 71, 71) !important;
vertical-align: middle !important;
font-size: 1.7rem !important;
`;
but it doesn't work!
When you wrap some component with styled hoc, it just passes className prop to your component.
IconContext.Provider expects only value prop. This prop is object and can contain style, attr or className values. You can just pass style attribute to configure it like this:
const MyProvider = ({children}) => <IconContext.Provider value={{ style: { someStyle: someValue } }}>{children}</IconContext.Provider>;
However, if you would like to use styled-components, it could be possible like this:
const MyProvider = ({className, children}) => <IconContext.Provider value={{className}}>{children}</IconContext.Provider>;
const MyProviderStyled = styled(MyProvider)`
some-style: some-value;
`;

idiomatic way to share styles in styled-components?

trying to port some code from jss to styled-components,
jss code looks something like:
//...
const styles = {
myStyles: {
color: 'green'
}
}
const {classes} = jss.createStyleSheet(styles).attach()
export default function(props) {
return (
<div>
<Widget1 className={classes.myStyles}/>
<Widget2 className={classes.myStyles}/>
</div>
)
}
my question is what would be the idiomatic way to accomplish this sharing of the same styles across multiple components?
You can either share actual CSS strings or share styled-components components:
Share CSS strings:
import {css} from 'styled-components'
const sharedStyle = css`
color: green
`
// then later
const ComponentOne = styled.div`
${sharedStyle}
/* some non-shared styles */
`
const ComponentTwo = styled.div`
${sharedStyle}
/* some non-shared styles */
`
Share actual styled-components:
const Shared = styled.div`
color: green;
`
// ... then later
const ComponentOne = styled(Shared)`
/* some non-shared styles */
`
const ComponentTwo = styled(Shared)`
/* some non-shared styles */
`
Update: Based on questions in the comments, I created an example to show that passing props to styled-components's css function works the same way as passing props to the components themselves: https://codesandbox.io/s/2488xq91qj?fontsize=14. The official recommendation from styled-components is to always wrap strings you will pass to styled-components in the css tag function. In this example, the Test component receives it background and foreground colors through passed-in props embedded in the cssString variable created by invoking the css function.
In addition to the posted answer, you can also create a function that accepts props / theme and returns the css``.
styled-components will check the type of the value provided eg: ${shared} and if its a function it will invoke it with the relevant props / theme.
import styled, {css} from 'styled-components';
const shared = ({theme, myProp}) => css`
color: ${theme.color};
`
/* ------------ */
const Component1 = styled.div`
${shared};
/* more styles ... */
`
const Component2 = styled.div`
${shared};
/* more styles ... */
`
In addition to the 2 answers above, you can also share style between tags as such:
const MyText = styled.div`
color: orange;
`
const MyLink = MyText.withComponent("a")

How to work with styled components in my react app?

I had trouble naming this question and it seems quite broad, so, forgive me oh moderators. I'm trying out styled components for the first time and trying to integrate it into my react app. I have the following so far:
import React from 'react';
import styled from 'styled-components';
const Heading = styled.h1`
background: red;
`;
class Heading extends React.Component {
render () {
return (
<Heading>
{this.props.title}
</Heading>
);
}
}
export default Heading;
So, just a normal class, but then I import styled components up top, define the const Heading, where I specify that a Heading really is just a styled h1. But I get an error stating that Heading is a duplicate declaration since I also say class Heading....
I'm obviously completely missing something here. All the examples online doesn't actually show how you also use this with React. I.e. where do I define my class, my constructor, set my state, etc.
Do I have to move the styled component into it's own file, i.e.:
import styled from 'styled-components';
const Heading = styled.h1`
background: red;
`;
export default Heading;
Then create a React component that will serve as a wrapper of sorts, e.g. 'HeadingWrapper':
import React from 'react';
import Heading from './Heading';
class HeadingWrapper extends React.Component {
render () {
return (
<Heading>
{this.props.title}
</Heading>
);
}
}
export default HeadingWrapper;
A bit of clarity on this would greatly be appreciated! Thanks :)
styled.h1`...` (for example) returns a React component that works just like <h1>. In other words, you use <h1> like this:
<h1>h1's children</h1>
...so when you do const Heading = styled.h1`...`;, you'll use <Heading> the same way:
<Heading>Heading's children</Heading>
If you want a component that behaves differently, e.g. one that uses the title prop instead of children, you'll need to define such a component, and it will need to have a different name than the Heading component you already defined.
For example:
const styled = window.styled.default;
const Heading = styled.h1`
background: red;
`;
const TitleHeading = ({title}) => <Heading>{title}</Heading>;
// ...or...
class StatefulTitleHeading extends React.Component {
render() {
return <Heading>{this.props.title}</Heading>;
}
}
ReactDOM.render(
<div>
<Heading>I'm Heading</Heading>
<TitleHeading title="I'm TitleHeading"/>
<StatefulTitleHeading title="I'm StatefulTitleHeading"/>
</div>,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/styled-components#1.4.3/dist/styled-components.js"></script>
<div id="container"></div>
Frankly, though, it makes more sense to just use the component returend by styled.h1 directly:
const Heading = styled.h1`...`;
export default Heading;
// ...then...
<Heading>Children go here</Heading>
The semantics of children are already clear, and using <Heading title="Children go here"/> instead detracts significantly from that.
Let me make this really simple for you.
Let's create one styled component for heading named 'Heading'
const Heading = styled.h1`
color: 'black';
font-size: 2rem;
`
and now you can use it like following.
<Heading>{this.props.title}</Heading>
How you manage to get the title prop as it's child is no concern of style component's. It only manages how that title looks. Styled component is not a container that maintains your app/business logic.
Now let's look at an example in it's entirety.
import styled from 'styled-components'
// Heading.js (Your styled component)
const Heading = styled.h1`
color: 'black';
font-size: 2rem;
`
export default Heading
and now your container that will use your styled component
// Header.jsx (Your container)
class Header extends Component {
componentWillReceiveProps(nextProps) {
// This your title that you receive as props
console.log(nextProps.title)
}
render() {
const { title } = this.props
return (
<div id="wrapper">
<Heading>{title}</Heading>
</div>
)
}
}
I hope that helps. Let me know if you need further clarification.

Categories

Resources