'How to use sx prop in styled components without mui

Instead of using multiple props for each css attribute, I want to make an sx prop like material-ui has. I'm trying to implement this with styled-components. The idea is that I can pass an object as a prop, and reference a value from the object in the styled component.

things to note:

  • material-ui is not added as a dependancy. I want to "clone" sx from it.
  • currently looking into prop-types to add some value in finding bug.

Button Component

import styled from "styled-components";

export const Button = styled.button`
  background-color: ${(sx) => sx.backgroundColor};
  color: ${(sx) => sx.color};
`;

Rendering Button

import React from "react";
import styled from "styled-components";
import { Button } from "./Button/Button";

function App() {
  return (
    <>
      <Button sx={{ backgroundColor: "red", color: "white" }} />
    <>
  );
}

export default App;

Update:

After adding prop-types to maybe find the issue, I get an error when I pass the prop to the Button component when I added this code:

// typechecking prop types passed
Button.propTypes = {
  sx: PropTypes.string,
};

And the error I got back:

Warning: Failed prop type: Invalid prop `sx` of type `object` supplied to `styled.button`, expected `string`

Im not sure exactly where its going wrong. I've tried doing a console.log to see the value passed, which seems to be a string. Therefore dot notation should work?

Any help would be appreciated, thanks very much :)



Solution 1:[1]

After adding prop-types and finding the passed types, I was able to find this answer:

// required prop to be passed as an object
Button.propTypes = {
  sx: PropTypes.object,
};

// updating the props for Button component
export const Button = styled.button`
  background-color: ${(props) => props.sx.backgroundColor};
  color: ${(props) => props.sx.color};
`;

then using sx as normal...

import React from "react";
import styled from "styled-components";
import { Button } from "./Button/Button";

function App() {
  return (
    <>
      <Button sx={{ backgroundColor: "red", color: "white" }} />
    </>
  );
}

export default App;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1