DEV Community

Cover image for How to use styled-system with typescript
Tim Richter (0DivTag)
Tim Richter (0DivTag)

Posted on • Edited on

17 6

How to use styled-system with typescript

Originally published at timrichter.dev

Styled-Components ❤️. There are a bunch of libraries already written for it one of which is styled-system which simplifies the creation of a component-based design system.

Now styled-system is awesome but I had some trouble finding good ways of integrating it with typescript especially when using custom components. So here is a little guide on how to do it 😉

Prerequisite

If you haven't already install the types for styled-system.

npm install -D @types/styled-system
# or with yarn
yarn add -D @types/styled-system
Enter fullscreen mode Exit fullscreen mode

Normally Styled Tags

import { layout, LayoutProps } from 'styled-system';

const Image = styled.img<LayoutProps>`
  ${layout}
`;
Enter fullscreen mode Exit fullscreen mode

Styled-Components doesn't know about us using the layout props in our Image Component so we have to declare it explicitly with "LayoutProps".

There is a props equivalent for everything in Styled-System for example color is ColorProps, space is SpaceProps and so on.

Custom Components

import { layout, LayoutProps, position, PositionProps } from 'styled-system';

interface Props extends PositionProps, LayoutProps {
  children: React.ReactNode;
}

const Container = styled.div<Props>`
  ${position};
  ${layout};
`;

const DropdownMenu: React.FC<Props> = ({ children, ...props }) => {
  return <Container {...props}>{children}</Container>;
};
Enter fullscreen mode Exit fullscreen mode

The important parts here are to pass the rest of the props to the element that should be styled (in this case 'Container') and merging layout, position and custom props (here 'children') into a single type and then passing that to the styled component and the component itself 😁

Advanced Custom Components

import { space, SpaceProps } from 'styled-system';

interface ContainerProps extends React.HTMLAttributes<HTMLDivElement> {
  isOwner: boolean;
}

type Props = ContainerProps & SpaceProps & {
    content: string;
};

const Container = styled.div<ContainerProps>`
  ${space};
  ${(props) =>
    props.isOwner ? 'align-self: flex-end' : 'align-self: flex-start'
   };
`;

const Message: React.FC<Props> = ({ content, isOwner, ...props }) => {
  return (
    <Container isOwner={isOwner} {...props}>
      {content}
    </Container>
  );
};
Enter fullscreen mode Exit fullscreen mode

This looks daunting 😅 We're gonna go through it one by one.

interface ContainerProps extends React.HTMLAttributes<HTMLDivElement> {
  isOwner: boolean;
}

const Container = styled.div<ContainerProps>`
  ${space};
  ${(props) =>
    props.isOwner ? 'align-self: flex-end' : 'align-self: flex-start'
   };
`;
Enter fullscreen mode Exit fullscreen mode

We want to give the styled div a custom prop "isOwner" to style it conditionally. For this we have to extend the props that the div element expects (HtmlAttributes)

type Props = ContainerProps & SpaceProps & {
    content: string;
};

const Message: React.FC<Props> = ({ content, isOwner, ...props }) => {
  return (
    <Container isOwner={isOwner} {...props}>
      {content}
    </Container>
  );
};
Enter fullscreen mode Exit fullscreen mode

We combine all props from the container, space props and our custom "content"-prop together into one type and pass that to the component.
In the end we can pass:

  • All Props that a normal div element would except, these would get passed to our Container
  • All Space Props from styled-system, these get also passed to our Container
  • Our Custom Props "isOwner" and "content", "isOwner" get's passed to the Container and "content" will be the child

We have a strongly typed Component that leverages styled-system, styled-components and custom props 🥳

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (5)

Collapse
 
aabhassao profile image
Aabhas Sao

Hey thanks, this is very helpful, was stuck before.

Collapse
 
aibolik profile image
Aibol Kussain

Should this @types/styled-system be a dev dependency?

Collapse
 
timrichter profile image
Tim Richter (0DivTag)

Yes it should! Thank you for the comment I updated the post to reflect that 😀

Collapse
 
skochdev profile image
Bohdan Skochii

wow, thank you, helped me to set styled-system and styled components together with TS. Great article!

Collapse
 
eyuelfrew profile image
Eyuel Frew

am new to this thing, and i couldn't find well written doc. just in case if you know one

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay