There have been some recent developments and with a new version of Typescript (eg. 3.0.1) and styled-components (eg. 3.4.5) there's no need for a separate helper. You can specify the interface/type of your props to styled-components directly.

interface Props {
  onPress: any;
  src: any;
  width: string;
  height: string;
}

const Icon = styled.Image<Props>`
  width: ${p => p.width};
  height: ${p => p.height};
`;

and if you want to be more precise and ignore the onPress

const Icon = styled.Image<Pick<Props, 'src' | 'width' | 'height'>>`
  width: ${p => p.width};
  height: ${p => p.height};
`;
Answer from elnygren on Stack Overflow
🌐
styled-components
styled-components.com › docs › basics
Styled Components Basic
This works perfectly fine with custom components too! const Button = styled.button` display: inline-block; color: #BF4F74; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid #BF4F74; border-radius: 3px; display: block; `; const ReversedButton = props => <Button {...props} children={props.children.split('').reverse()} /> render( <div> <Button>Normal Button</Button> <Button as={ReversedButton}>Custom Button with Normal Button styles</Button> </div> );
🌐
Emotion
emotion.sh › docs › styled
Emotion – Styled Components
To use styles from a styled component but change the element that's rendered, you can use the as prop.
Discussions

How do I provide props to styled elements in Typescript?
I looked at the docs and other than creating a whole empty component purely for providing a definition of props I'm not sure of if it's possible to provide custom props to a styled element ... More on github.com
🌐 github.com
100
March 30, 2017
Typescript using custom props
The last example in the Using custom props section in the typescript documentation is broken or at least misleading. I think it should more look like this, or at least this is the way I got it to w... More on github.com
🌐 github.com
5
April 10, 2020
React — Passing props with styled-components
I just read in the styled-components documentation that the following is wrong and it will affect render times. If that is the case, how can I refactor the code and use the required props to create a More on stackoverflow.com
🌐 stackoverflow.com
Updated packages, now my styled-components pass all their custom props to the DOM, triggering an Unknown Prop Warning everywhere...
I've an idea; use transient props ($ prefix) for stuff you don't want to be passed to child component More on reddit.com
🌐 r/reactjs
9
1
January 10, 2024
🌐
styled-components
styled-components.com › docs › api
styled-components
Learn more about this constructor in the Attaching Additional Props section. If you want to keep all the styling you've applied to a component but just switch out what's being ultimately rendered (be it a different HTML tag or a different custom component), you can use the "as" prop to do this ...
🌐
GitHub
github.com › styled-components › styled-components › issues › 630
How do I provide props to styled elements in Typescript? · Issue #630 · styled-components/styled-components
March 30, 2017 - I looked at the docs and other than creating a whole empty component purely for providing a definition of props I'm not sure of if it's possible to provide custom props to a styled element other than theme. Example For the above example ...
Author   tal
🌐
LogRocket
blog.logrocket.com › home › 8 awesome features of styled-components
8 awesome features of styled-components - LogRocket Blog
June 4, 2024 - const InheritedDiv = styled(Div)` ... border: 1px solid palevioletred; Props can be passed to styled components just as they are with regular React components (class or functional)....
🌐
Smashing Magazine
smashingmagazine.com › 2020 › 07 › styled-components-react
How To Use Styled-Components In React — Smashing Magazine
Notice how we don’t need a ternary when setting the width? That’s because we’ve already set a default for it with width: props.width || "100%",. Also, we used CSS custom properties because we can! Note: If styled components are React components, and we can pass props, then can we also ...
Find elsewhere
🌐
GitHub
github.com › styled-components › styled-components-website › issues › 630
Typescript using custom props · Issue #630 · styled-components/styled-components-website
April 10, 2020 - The last example in the Using custom props section in the typescript documentation is broken or at least misleading. I think it should more look like this, or at least this is the way I got it to work in my project. I am not sure whether an additional & HeaderProps is better in the generic type section, but I got it to work without. const Title = styled(({ isActive, ...rest }) => <Header {...rest} />)<{ isActive: boolean }>` color: ${props => (props.isActive ?
Author   markatk
Top answer
1 of 7
76

I believe what the documentation is saying is that you should avoid including your styles inside of the rendering component:

DO THIS

const StyledWrapper = styled.div`
  /* ... */
`

const Wrapper = ({ message }) => {
  return <StyledWrapper>{message}</StyledWrapper>
}

INSTEAD OF THIS

const Wrapper = ({ message }) => {
  // WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!!
  const StyledWrapper = styled.div`
    /* ... */
  `

  return <StyledWrapper>{message}</StyledWrapper>
}

Because what happens is when the component's Props changes, then the component will re-render and the style will regenerate. Therefore it makes sense to keep it separate.

So if you read further on to the Adapting based on props section, they explain this:

const Button = styled.button`
  /* Adapt the colours 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;
`;

// class X extends React.Component {
//  ...

render(
  <div>
    <Button>Normal</Button>
    <Button primary>Primary</Button>
  </div>
);

// }

this works because when you use the Button component in class X, it will know the props of class X without you having to tell it anything.

For your scenario, I imagine the solution would be simply:

const TabWrapper = styled.li`
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 100px;
  margin: 1px;
  font-size: 3em;
  color: ${props => (props.isSelected ? `white` : `black`)};
  background-color: ${props => (props.isSelected ? `black` : `#C4C4C4`)};
  cursor: ${props => (props.isSelected ? 'default' : `pointer`)};
`;

const Tab = ({ onClick, isSelected, children }) => {
  return <TabWrapper onClick={onClick}>{children}</TabWrapper>
}

const X = <Tab onClick={() => console.log('clicked')} isSelected>Some Children</Tab>

I haven't tested this at all, so please feel free to try it out and let me know if it works for you or whatever worked for you!

2 of 7
57

You can pass an argument with Typescript as follows:

<StyledPaper open={open} />    

...

const StyledPaper = styled(Paper)<{ open: boolean }>`
   top: ${p => (p.open ? 0 : 100)}%;
`;
🌐
DEV Community
dev.to › britotiagos › using-props-on-styled-component-and-nextjs-51lk
Using props on styled-component and next.js - DEV Community
March 3, 2022 - ${(props) => props.secondary && ` background: #f00; color: #00a8; border-radius: 0 `}; ... Some people will find this a bit too hard to read, but if you have the correct format or styles in your code editor it will become easy to read.
🌐
Reddit
reddit.com › r/reactjs › updated packages, now my styled-components pass all their custom props to the dom, triggering an unknown prop warning everywhere...
r/reactjs on Reddit: Updated packages, now my styled-components pass all their custom props to the DOM, triggering an Unknown Prop Warning everywhere...
January 10, 2024 -

I was so happy in my previous repo with styled-components 5.3.6, making thousands of styled-components components with all that dynamic stuff with the help of custom props. I made sure to respect the reserved prop names like 'disabled' (I would call it isDisabled instead) and it was awesome.

Now, new project, new repo, I decide to take the latest packages, including styled-components 6.1.2 and I would adapt to new changes. For once I even managed to avoid the usual. So I work for many hours without noticing any red warning in the console related to my custom props... until today:

Warning: React does not recognize the `isPanelExpanded` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `ispanelexpanded` instead. If you accidentally passed it from a parent component, remove it from the DOM element.

Of course it doesn't recognize it. That prop was never meant for the DOM elements. And I suppose this is why:

Dropped automatic prop filtering; use transient props ($ prefix) for stuff you don't want to be passed to child component / HTML (styled-components/releases/tag/v6.0.0)

The workarounds:

  1. $isPanelExpanded. Ugly.

  2. styled('div').withConfig({ shouldForwardProp: (prop) => !['isPanelExpanded'].includes(prop)}). No. Just.. no.

  3. Roll back to an outdated styled-components like a piece of sh**?

Someone please tell me I missed the simple elegant solution to this nonsense. Wake me from this nightmare, please. *screams (from home, not at the office)*

🌐
GitHub
github.com › styled-components › styled-components › issues › 2449
Styled Components not passing props when using `as` prop · Issue #2449 · styled-components/styled-components
March 15, 2019 - import React from "react"; import styled from "styled-components"; class Dropdown extends React.Component { constructor(props) { super(props); this.state = { open: false }; } toggleDropdown = e => { console.log("toggling dropdown"); const open = !this.state.open; this.setState({ ...this.state, open }); }; render() { const { as: Tag, className, children, dropHeader } = this.props; console.log(this.props); console.log("dropdown rendering"); // comment return ( <Tag className={className}> <h2 onClick={this.toggleDropdown}>{dropHeader}</h2> {this.state.open && children} </Tag> ); } } Dropdown.defaultProps = { as: "nav" };
Author   whoisryosuke
🌐
Stack Overflow
stackoverflow.com › questions › 57078388 › passing-custom-props-to-each-styled-component-through-provider
reactjs - Passing custom props to each styled component through Provider - Stack Overflow
July 17, 2019 - I would like to pass a custom prop (exactly: theme name as string) to each passed styled component through Provider, so it was available throughout the css definition. ThemeProvider almost does it,...
🌐
MUI
mui.com › system › styled
styled() - MUI System
styled is a function, while sx is a prop available on the components created with styled.
🌐
GitHub
github.com › styled-system › styled-system › blob › master › docs › custom-props.md
styled-system/docs/custom-props.md at master · styled-system/styled-system
To extend Styled System for other CSS properties that aren't included in the library, use the system utility to create your own style functions. All Styled System functions rely on these low-level utilities. ... import styled from 'styled-components' import { system } from 'styled-system' const textDecoration = system({ prop: 'textDecoration', cssProperty: 'textDecoration', }) const Link = styled.a` ${system({ textDecoration: true, fontWeight: { property: 'fontWeight', scale: 'fontWeights', }, })} ` export default Link
Author   styled-system
🌐
TecForFun
tecforfun.com › home › css
How to work with props in Styled-components - –TecForFun
January 4, 2023 - An important thing to note here is that you need to make sure the relevant attribute passes to the component. for example, if you create a <li> tag and pass the attribute “type” as a prop to the component, it will not have the same effect as above. Not only have HTML attributes, but you can also pass custom props and apply styles based on the prop.
🌐
Panda-css
panda-css.com › docs › concepts › style-props
Style props | Panda CSS - Panda CSS
To make a custom JSX component that accepts style props, Use the splitCssProps function to split style props from other component props.
Top answer
1 of 5
62

Yes!

The most basic example of the above would look like this in MUI v5:

const Div = styled("div")(({ primary }) => ({
  backgroundColor: primary ? "palevioletred" : "white",
  color: primary ? "white" : "palevioletred"
}));


render(
  <section>
    <Div>Normal</Div>
    <Div primary>Primary!</Div>
  <section>
);

However, as the React docs say:

The unknown-prop warning will fire if you attempt to render a DOM element with a prop that is not recognized by React as a legal DOM attribute/property. You should ensure that your DOM elements do not have spurious props floating around.

So MUI gave us the shouldForwardProp option to tell MUI whether it "should forward the prop" to the root node or not. The above example would look like this using that prop:

const Div = styled("div", {
  shouldForwardProp: (prop) => prop !== "primary"
})(({ primary }) => ({
  backgroundColor: primary ? "palevioletred" : "white",
  color: primary ? "white" : "palevioletred"
}));

render(
  <section>
    <Div>Normal</Div>
    <Div primary>Primary!</Div>
  <section>
);

Explanation

The second argument to the styled function is an options object, one of the things it accepts is shouldForwardProp, which as the docs say, "Indicates whether the prop should be forwarded to the Component". So to remove the unknown prop warning from the console, we tell it not to pass our custom prop to the DOM element with shouldForwardProp: (prop) => prop !== "primary". Now we destructure this prop in the function call that returns our custom styles, and use it in those styles like we would any other function.

If you want to use the global theme styles here as well, just destructure it along with your custom prop(s), ie ({ primary, otherProp, thirdProp, theme }).

Working codesandbox.

MUI v5 styled API docs

2 of 5
31

Here is a fully-working MUI v5 TypeScript example where you can pass custom properties to a styled component:

import React from 'react';
import { Button, styled, Typography } from '@mui/material';

const PREFIX = 'NimbusButton';
const classes = {
    root: `${PREFIX}-root`,
    button: `${PREFIX}-button`
};

interface RootProps {
    textColor?: 'primary' | 'secondary';
    buttonTextColor?: 'primary' | 'secondary';
}

const Root = styled('div', {
    shouldForwardProp: (prop) => prop !== 'textColor' && prop !== 'buttonTextColor',
    name: 'MyThemeComponent',
    slot: 'Root'
})<RootProps>(({ theme, textColor, buttonTextColor }) => ({
    [`& .${classes.root}`]: {
        color: textColor ? theme.palette.primary.main : theme.palette.secondary.main
    },
    [`& .${classes.button}`]: {
        color: buttonTextColor ? theme.palette.primary.main : theme.palette.secondary.main
    }
}));

type OwnProps = {
    textColor: 'primary' | 'secondary';
    buttonTextColor: 'primary' | 'secondary';
    text?: string;
    buttonText: string;
};

const CustomStyledButton: React.FC<OwnProps> = (props) => {
    const { textColor, buttonTextColor, text, buttonText } = props;
    return (
        <Root className={classes.root} textColor={textColor} buttonTextColor={buttonTextColor}>
            {text && <Typography variant={'body1'}>{text}</Typography>}
            <Button className={classes.button}>{buttonText}</Button>
        </Root>
    );
};

export default CustomStyledButton;
🌐
Medium
byrayray.medium.com › how-to-add-props-to-styled-components-in-react-js-with-typescript-1df49ef951bf
How To Add Props To Styled Components in React.js with TypeScript | by RayRay | Medium
March 16, 2021 - I define the property state in my interface, and I tell that I accept only the values of the sendState enum. So if I put in another value, my IDE and build system starts complaining. TypeScript helps me write predictable code, as you can see. You usually define a styled-component like: export const StatusMessage = styled.div this.
🌐
Sentry
develop.sentry.dev › frontend › using-styled-components
Using Styled Components - Sentry Developer Documentation
This does create overhead at runtime and should be avoided. What follows is an example of how to pass custom props, and how to avoid doing so. ... import styled from "@emotion/styled"; // ❌ Try to avoid this const Label = styled("label")<{ isDisabled: boolean; isError: boolean }>` color: ${(p) => p.isDisabled ?