blankface
blankface

Reputation: 6347

if statement inside styled component

export enum SizeEnum {
    Small,
    Large
}

export interface ICheckbox {
    Size: SizeEnum;
}

const Box = styled.div`
    height: 20px;
    width: 20px;
`

In the above code I want to be able to conditionally change the height and width value of <Box> based on the prop. How do I do this?

Upvotes: 8

Views: 36447

Answers (8)

Cuminato
Cuminato

Reputation: 542

Get rid of all IFs

I know that this question is pretty old but I would like to contribute with one suggestion

Lately I've come up with a pattern to compute the value using an object, I think this ended up being pretty interesting!

// types.ts
export type CheckboxSize: 'Small' | 'Large'

export interface ICheckbox {
    Size: CheckboxSize;
}


// styles.ts
import styled, { css } from 'styled-components'
import type { CheckboxSize } from './types.ts' 

interface GetBoxSizeProps { 
  size: CheckboxSize
}

function getBoxSize ({ size }: GetBoxSizeProps) => ({
  'Small': css`
    height: 16px;
    width: 16px;
  `,
  'Large': css`
    height: 20px;
    width: 20px;    
  `,
}[size])

interface BoxProps {
  size: CheckboxSize
}

/*
  Just by placing the function here, it will be automatically 
  called by styled components and computed
*/
const Box = styled.div<BoxProps>`
  ${getBoxSize}

  //other styles...
`

// usage

<Box size="Small" />
<Box size="Large" />

My problem with the old "if" and "switch" styles was that after some props, the styles logic often times grow up into something that's quite verbose and hard to mantain

I'm not clamming this pattern as my invention, but I wasn't able to find something similar anywhere!

Hope this help someone :)

Ps: if you use themes, is possible to pass the property to the function and keep it pure!

Upvotes: 0

subharb
subharb

Reputation: 3472

Another way to do this, if you want to add several css styles.

import css from "styled-jsx/css";


const Box = styled.div`
    height:100px;
    width:100px;
    ${props => props.Size === 'Small' && css`
         height:20px;
         width:20px;
    `}
`

Upvotes: 24

aderchox
aderchox

Reputation: 4074

Actual if/else syntax may be used as well, what matters is, the returned value should be a string:

const DrawerItemTitle = styled.div<{isExpanded: boolean}>(props => {
    const baseStyles = `
        white-space: nowrap;
    `;
    const expandedStyles = baseStyles + `
        opacity: 1;
        transition: opacity 0.4s;
        text-align: center;
        flex-grow: 1;`
    const notExpandedStyles = baseStyles + `
        opacity: 0;
        transition: opacity 0s;
        position: absolute;
        width: 100%;
    `;

    if(props.isExpanded) {
        return expandedStyles; 
    }
    else { 
        return notExpandedStyles;
    }
);

Upvotes: 1

chazefate
chazefate

Reputation: 822

You can add interface in TypeScript and use booleans for default, small and large boxes. This example is for those who has more than two choices. In case of two choices, I would use arrow function and ? : operators.

interface Sizes { 
  small?: boolean, 
  large?: boolean 
}

// Box.
const Box = styled.div<Sizes>`
  // p in this case means parameter which can have small and large booleans
  height: ${p => 
    (p.small && '25px') ||
    (large && '100px') || 
    '50px'
  };

  width: ${({Size}) => 
    (small && '25px') || 
    (large && '100px') || 
    '50px'
  };

`

// Render.
<Box/> // 50px - Normal.
<Box small/> // 25px - Small.
<Box large/> // 100px - Large.

Upvotes: 1

Haroun Hajem
Haroun Hajem

Reputation: 5628

You can use the elvis operator in something like this:

${(props) => props.someValue ? css` width: 20px;` : css` width: 100px; `}

Hope this helps someone looking into how to use logical operators in React styled components.

Upvotes: 3

Naveen DA
Naveen DA

Reputation: 4380

We can add the if-checks just like jsx

const Box = styled.div`
    height:100px;
    width:100px;
    ${props => props.Size === 'Small' && `
         height:20px;
         width:20px;
    `}
` 

Note: No need to include the word css

Upvotes: 2

Arman Charan
Arman Charan

Reputation: 5797

See Logical Operators and Adapting based on props for more info.

// Box.
const Box = styled.div`

  height: ${({Size}) => 
    Size === 'Small' && '25px' ||
    Size === 'Large' && '100px' || 
    '50px'
  };

  width: ${({Size}) => 
    Size === 'Small' && '25px' || 
    Size === 'Large' && '100px' || 
    '50px'
  };

`

// Render.
<Box/> // 50px - Normal.
<Box Size="Small"/> // 25px - Small.
<Box Size="Large"/> // 100px - Large.

Upvotes: 15

Amit Kumar
Amit Kumar

Reputation: 113

You can use the ternary operator

const Box = styled.div`
height: ${props => props.Size === 'Small' ? '20px' : '40px'}
width: ${props => props.Size === 'Small' ? '20px' : '40px'}
`

Reference: https://www.styled-components.com/docs/basics

Upvotes: 6

Related Questions