Search code examples
javascriptreactjsstyled-components

How to handle conditionals in a styled component


I am adding theme support for my app with styled components and ThemeProvider. The component in question already had a conditional to display style based on prop. When I introduce the theme I can't get the styles I need on the border property. They're just ignored. If replace them with a hex value I can see a border.

const Wrapper = styled.div`
  position: relative;
  width: 100px !important;
  height: 130px !important;
  opacity: ${({ isDragging }) => (isDragging ? 0.25 : 1)};
  border: ${({ isSelected }) =>
    isSelected
      ? `1px solid ${props => props.theme.CYAN}`
      : `1px solid ${props => new Color(props.theme.CYAN).alpha(0.25)}`};
  text-align: center;
  padding: 10px !important;
  margin: 4px !important;
  box-shadow: none;
  border-radius: 0;
  cursor: pointer;
  box-sizing: border-box;
  background-color: ${({ isSelected }) =>
    isSelected
      ? props => new Color(props.theme.CYAN).alpha(0.25)
      : props => props.theme.DARK} !important;

  & :hover {
    border-color: ${props => props.theme.CYAN};
    box-shadow: none;
  }
}

<Wrapper
        isDragging={isDragging}
        isSelected={isSelected}
        onClick={onClick}
        className="daily-item"
      >


export const CLASSIC_THEME = {
  DARK: '#282a2b',
  LIGHT: 'white',
  CYAN: '#2edaf4',
  GREEN: '#26fba3',
  PURPLE: '#6f24bd',
  PINK: '#dd2df4',
  LIGHT_PURPLE: '#6d47f6',
  RED: '#f42d61',
  GREY: '#a6a6a6',
};

export const PRIMARY_THEME = {
  DARK: '#1f2630',
  LIGHT: '#EEEEFF',
  CYAN: '#BFC0C0',
  GREEN: '#9FB4C7',
  PURPLE: '#6f24bd',
  PINK: '#C89047',
  LIGHT_PURPLE: '#6d47f6',
  RED: '#f42d61',
  GREY: '#a6a6a6',
};

I'm aware these keys are not accurately describing the hex value :) I'm gonna get to that


Solution

  • You are using a tagged template literal on the styled div, that's how you get a reference to props. In your approach however I notice you deconstruct the isSelected property out of props and then attempt to use props by adding another arrow function inside, which is not part of the tagged template literal. I'm guessing that's why it does not work. Try the following:

    const Wrapper = styled.div`
      position: relative;
      width: 100px !important;
      height: 130px !important;
      opacity: ${({ isDragging }) => (isDragging ? 0.25 : 1)};
      border: ${props =>
        props.isSelected
          ? `1px solid ${props.theme.CYAN}`
          : `1px solid ${new Color(props.theme.CYAN).alpha(0.25)}`};
      text-align: center;
      padding: 10px !important;
      margin: 4px !important;
      box-shadow: none;
      border-radius: 0;
      cursor: pointer;
      box-sizing: border-box;
      background-color: ${props =>
        props.isSelected
          ? new Color(props.theme.CYAN).alpha(0.25)
          : props.theme.DARK} !important;
    
      & :hover {
        border-color: ${props => props.theme.CYAN};
        box-shadow: none;
      }
    `;