Variants

Stitches supports a first-class variant API.

Adding variants

const Button = styled('button', {
  borderRadius: '9999px',
  fontSize: '15px',
  lineHeight: '1',
  fontWeight: 500,
  height: '35px',
  paddingLeft: '15px',
  paddingRight: '15px',
  border: '0',

  variants: {
    color: {
      violet: {
        backgroundColor: 'blueviolet',
        color: 'white',
        ':hover': {
          backgroundColor: 'darkviolet',
        },
      },
      gray: {
        backgroundColor: 'gainsboro',
        ':hover': {
          backgroundColor: 'lightgray',
        },
      },
    },
  },
});

render(
  <div style={{ display: 'flex', gap: '20px' }}>
    <Button color="violet">Button</Button>
    <Button color="gray">Button</Button>
  </div>
);

A variant accepts the same style object as the base styles.

Multiple variants

const Button = styled('button', {
  borderRadius: '9999px',
  lineHeight: '1',
  fontWeight: 500,
  border: '0',

  variants: {
    color: {
      violet: {
        backgroundColor: 'blueviolet',
        color: 'white',
        ':hover': {
          backgroundColor: 'darkviolet',
        },
      },
      gray: {
        backgroundColor: 'gainsboro',
        ':hover': {
          backgroundColor: 'lightgray',
        },
      },
    },
    size: {
      small: {
        fontSize: '13px',
        height: '25px',
        paddingRight: '10px',
        paddingLeft: '10px',
      },
      large: {
        fontSize: '15px',
        height: '35px',
        paddingLeft: '15px',
        paddingRight: '15px',
      },
    },
  },
});

render(
  <div style={{ display: 'flex', gap: '20px', alignItems: 'center' }}>
    <Button color="gray" size="small">
      Button
    </Button>
    <Button color="violet" size="small">
      Button
    </Button>
    <Button color="gray" size="large">
      Button
    </Button>
    <Button color="violet" size="large">
      Button
    </Button>
  </div>
);

Compound variants

In the case of needing to set styles of a variant, based on a combination of other variants, you can use the compoundVariant function:

Button.compoundVariant(
  {
    color: 'violet',
    appearance: 'outline',
  },
  {
    color: 'blueViolet',
    borderColor: 'darkviolet',
    ':hover': {
      color: 'white',
    },
  }
);

The compoundVariant function takes two arguments, the first one is an object that defines a combination of variants to be used as the condition for the compound variant, the second is the style object that should be applied when that condition is met.

const Button = styled('button', {
  borderRadius: '9999px',
  lineHeight: '1',
  fontWeight: 500,
  border: '0',
  fontSize: '13px',
  height: '25px',
  paddingRight: '10px',
  paddingLeft: '10px',

  variants: {
    color: {
      violet: {
        backgroundColor: 'blueviolet',
        color: 'white',
        ':hover': {
          backgroundColor: 'darkviolet',
        },
      },
      gray: {
        backgroundColor: 'gainsboro',
        ':hover': {
          backgroundColor: 'lightgray',
        },
      },
    },
    appearance: {
      outline: {
        backgroundColor: 'transparent',
        borderWidth: '1px',
        borderStyle: 'solid',
      },
    },
  },
});

Button.compoundVariant(
  {
    color: 'violet',
    appearance: 'outline',
  },
  {
    color: 'blueViolet',
    borderColor: 'darkviolet',
    ':hover': {
      color: 'white',
    },
  }
);

Button.compoundVariant(
  {
    color: 'gray',
    appearance: 'outline',
  },
  {
    color: 'gray',
    borderColor: 'lightgray',
    ':hover': {
      color: 'black',
    },
  }
);

render(
  <div style={{ display: 'flex', gap: '20px', alignItems: 'center' }}>
    <Button color="violet">Button</Button>
    <Button color="gray">Button</Button>
    <Button color="violet" appearance="outline">
      Button
    </Button>
    <Button color="gray" appearance="outline">
      Button
    </Button>
  </div>
);

Default variants

You can use React's defaultProps to set a variant as initial:

const Button = styled('button', {
  borderRadius: '9999px',
  fontSize: '15px',
  lineHeight: '1',
  fontWeight: 500,
  height: '35px',
  paddingLeft: '15px',
  paddingRight: '15px',
  border: '0',

  variants: {
    color: {
      violet: {
        backgroundColor: 'blueviolet',
        color: 'white',
        ':hover': {
          backgroundColor: 'darkviolet',
        },
      },
      gray: {
        backgroundColor: 'gainsboro',
        ':hover': {
          backgroundColor: 'lightgray',
        },
      },
    },
  },
});

Button.defaultProps = {
  color: 'violet',
};

render(<Button>Button</Button>);