Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional styling using Styled Components

I've been trying for hours to figure this out, and I'm sure the answer is simple. When an Item is clicked, it will ultimately create a filter for my todo list. What I'm struggling to do is apply conditional styling, so that the font color of the 'active' item is blue.

I have included status as a prop, but I can't seem to use it as well as props inside the styled components.

From my App.js:

import { useState } from 'react'

function App() {
  const [ status, setStatus ] = useState("all")

  return (
    <Filter status={status} setStatus={setStatus}/>
  )
}

Filter.js

const Container = styled.div`
    display: flex;
    justify-content: center;
`

const Item = styled.p`
   color: red;

   // I'm trying to do something like this..

   ${(status, props) => {
        if (status === props.id) {
            return `
                color: blue;
            `
        }
    }}
   
`

export const Filter = ({ setStatus, status }) => {
    
    const statusHandler = (e) => {
        if (e.target.id) {
            setStatus(e.target.id)        
        }
    }
    
    return (
        <div>
          <Container onClick={statusHandler}>
            <Item id="all">All</Item>
            <Item id="active">Active</Item>
            <Item id="completed">Completed</Item>
          </Container>
        </div>
    )
}
like image 996
sazzledazzle Avatar asked Oct 20 '25 14:10

sazzledazzle


2 Answers

Pass both the status and id props to the Item component and do the comparison in the props callback.

const Item = styled.p`
  color: red;

  ${({ id, status }) => status === id && 'color: blue; '}
`;

Usage:

<Item id="all" status={status}>All</Item>

Demo

Edit conditional-styling-using-styled-components

You could make this simpler though with a single prop and do the conditional test in the component.

const Item = styled.p`
  color: red;

  ${({ isStatusMatch }) => isStatusMatch && "color: blue;"}
`;

...

<Item isStatusMatch={status === 'all'}>All</Item>

Full demo code:

const Item = styled.p`
  color: red;
  ${({ id, status }) => status === id && "color: blue;"}
`;

const Item2 = styled.p.attrs(({ id, status }) => ({
  className: id === status && "statusMatch"
}))`
  color: red;
  &.statusMatch {
    color: blue;
  }
`;

const Item3 = styled.p`
  color: red;
  ${({ statusMatch }) => statusMatch && "color: blue;"}
`;

function App() {
  return (
    <div className="App">
      <Item id="test" status="test">
        test
      </Item>
      <Item id="nottest" status="test">
        not test
      </Item>

      <Item2 id="test" status="test">
        test
      </Item2>
      <Item2 id="nottest" status="test">
        not test
      </Item2>

      <Item3 statusMatch={"test" === "test"}>test</Item3>
      <Item3 statusMatch={"nottest" === "test"}>not test</Item3>
    </div>
  );
}

enter image description here

like image 82
Drew Reese Avatar answered Oct 23 '25 05:10

Drew Reese


I think the easiest way to perform this task is to add a class at the element you want to change the color.

So you're item will be

const Item = styled.p`
   color: black;
   &.selected {
    color: red
   }

and you're Component will be:

<>
    <Item id="all" className={status === "all" ? "selected" : null}>All</Item>
    <Item id="active" className={status === "active" ? "selected" : null}>Active</Item>
    <Item id="completed" className={status === "completed" ? "selected" : null}>Completed</Item>
</>

To avoid to write repeating code you can loop the values. And here we go:

const items = [
    {
        id: "all",
        value: "All"
    },
    {
        id: "active",
        value: "Active"
    },
    {
        id: "completed",
        value: "Completed"
    },
]

items.map(({id, value}) => (
    <Item key={id} id={id} className={status === id ? "selected" : null}>{value}</Item>
))

There's no need to put logic in Styled Component if you can keep in React

like image 31
the_previ Avatar answered Oct 23 '25 04:10

the_previ