Moshe
Moshe

Reputation: 6991

Handling Combinations of Props in Styled Components

I am trying to implement a material designed based button component using styled-components. The component will have a number of props (such as size, icon, floating, etc).

It is getting rather overwhelming, though, to manage all the various combinations of props.

For instance, buttons come in three sizes: default, small and large.

But the size of a small button changes based on whether or not it is a regular button or a floating button. The same goes for a large button.

So I have the following sizes:

And, of course, I have other combinations that I haven't listed.

As a result, my code is starting to get a bit convoluted as I have to not only check for the existence of a prop (${props => { if (props.floating)...), but also for whether or not that particular prop exists in combination with another prop (${props => { if (props.floating && props.small)...).

As such, I am wondering if anyone has any suggestions on how to best organize and structure props when dealing with large numbers of combinations?

Thanks.

Upvotes: 0

Views: 2854

Answers (3)

Ted
Ted

Reputation: 14927

I prefer to keep my css separate, like in a styles.js file. Take the following code for example. It keeps the css organized, and makes implementing the different options pretty clean. Of course, add your css into the appropriate definitions

//styles.js
import { css } from 'styled-components';

export const buttonbase = css`/*base styles for all buttons*/`;
export const small = css`/*small size styles*/`;
export const medium = css`/*default size styles*/`;
export const large = css`/*large size styles*/`;
export const floating = css`/*float styles*/`;

And in your component file:

//Button.js
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import * as Styles from './styles';

const propTypes = {
  floating: PropTypes.bool,
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  children: PropTypes.node,
};

const defaultProps = {
  floating: false,
  size: 'medium',
};

const ButtonBase = styled.button`
  ${Styles.buttonbase};
  ${props => (props.floating ? Styles.floating : '')};
  ${props => Styles[props.size]};
`;

const Button = ({ floating, size, children, ...rest }) => (
  <ButtonBase
    size={size}
    floating={floating}
    {...rest}
  >
    {children}
  </ButtonBase>
);

Button.propTypes = propTypes;
Button.defaultProps = defaultProps;

export default Button;

The result would be, say given these values:

export const buttonbase = css`
  border: 1px solid black;
  padding: 10px;
`;
export const medium = css`
  font-size: 16px;
  height: 30px;
`;
export const floating = css`
  float: left;
`;

And this component:

<Button size="medium" floating />

The <ButtonBase/> component puts together buttonbase, medium, and floating from the imported styles, generating the complete style:

  border: 1px solid black;
  padding: 10px;
  font-size: 16px;
  height: 30px;
  float: left;

Upvotes: 2

Marwane Boudriga
Marwane Boudriga

Reputation: 191

I use a package called styled-is to help style my styled-components, it comes with helper functions you just use directly with styled-components.

Upvotes: 1

Stephen Burke
Stephen Burke

Reputation: 459

Keep in mind you can destructure within your instantiation. For example you might write like so:

${({ floating, small }) => {
    if (floating && small){
    ...
    }
}

It will cut down some of the bloat.

Upvotes: 3

Related Questions