Helper function to create React component with pre-filled Tailwind classes

Viewed 25

I sometimes extract local Tailwind-styled components like this:

const Container: React.FC = ({ children }) => (
  <div className="bg-white px-5 py-5">
    {children}
  </div>
);

To make this easier, I would love to have a helper styleElement function that would create the Container for me, a bit like this:

const Container = styleElement("div", "bg-white px-5 py-5");

How would I write the styleElement function so that Container is correctly typed as a div and setting its className adds to the defaults? Ie:

// Renders as <div className="bg-white px-5 py-5 text-red">…</div>
<Container className="text-red">…</Container>

I stress that I want to keep the typing right/tight, so that calling styleElement("a", …) would produce a component that accepts the correct props for an a.

PS. I have seen this related question, but I’m having trouble pivoting the types from the answer there to what I want.

1 Answers

The function

function createElement(tag, classes) {
  return ({ children }) => {
    const Element = tag;

    return <Element className={classes}>{ children }</Element>
  }
}

Based on this answer

Usage

function App() {
  const StyledDiv = createElement('div', 'p-4')
  return (
    <div className="App">
      <StyledDiv>Hello</StyledDiv>
    </div>
  );
}

Basic props

function createElement(tag: keyof JSX.IntrinsicElements, classes: string) {
  return ({
    children,
    ...props
  }: React.DetailedHTMLProps<
    React.BlockquoteHTMLAttributes<HTMLElement>,
    HTMLElement
  >) => {
    return React.createElement(tag, { ...props, className: classes }, children);
  };
}
Related