Is there a way to apply styles to a checkbox's child element depending on the checkbox's state without relying on ternary operators within Styled Components?

I am currently working on styling this component using Styled Components, but I feel like my current approach is a bit of a hack. What would be the best practice for incorporating Styled Components to style this component effectively?

If I were to use Plain HTML and CSS, the structure would look something like this:

HTML:

<label>
  <input type="checkbox" value="s1"/>
  <div class="container">s1</div>
</label>
<label>
  <input type="checkbox" value="s2"/>
  <div class="container">s2</div>
</label>
<label>
  <input type="checkbox" value="s3"/>
  <div class="container">s3</div>
</label>
<label>
  <input type="checkbox" value="s4"/>
  <div class="container">s4</div>
</label>

CSS:

input[type=checkbox] {
  position: absolute;
  width: 0;    
}

.container {
  width: 5em;
  border: solid #aaa 1px;
  background: #fff
  color: #000;
}
.container:hover {
  background: #999;
}  

.container:active {
  background: #333;
  color:#fff
}

input[type=checkbox]:checked + .container {   
  background: #000;
  color: #fff;
}    

input[type=checkbox]:checked + .container:hover {
  background: #ddd;
}  

input[type=checkbox]:checked + .container:hover:active {
  background: white;
  color: black;
}  

When using a React component with Styled Components, the process can be achieved, however, I find it cumbersome to use two different Styled Components along with a ternary operator compared to achieving the same result directly in CSS using

input[type=checkbox]:checked + .container
.

import React, { useState } from 'react';
import styled from 'styled-components'

function Test() {
  const [selectedStations, setSelectedStations] = useState([]);  

  const Input = styled.input`
    position: absolute;
    width: 0;    
  ` 
  const UncheckedContainer = styled.div` 
    width: 5em;    
    border: solid #aaa 1px;
    background: #fff;
    color: #000;

  &:hover {
    background: #999;
  }  

  &:active {
      background: #333;
      color: #fff;
  }
  `
  const CheckedContainer = styled.div`
    width: 5em;
    border: solid black 1px;
    background: #000;
    color: #fff;

  &:hover {
    background: #ddd;
  }  

  &:active {
      background: #fff;
      color: #000;
  }  
  `

  function selectStations(e) {    
    let station = e.target.value;
    const s = [...selectedStations]
    const stationIndex = s.indexOf(station)

    if (stationIndex > -1) {
      s.splice(stationIndex, 1);
    } else {
      s.push(station);
      s.sort();
    }

    setSelectedStations(s)
  };


  return (
    <div>
        {new Array(4).fill('').map((v, i) =>{

          let checked = selectedStations.indexOf(`s${i+1}`) > -1         

          return(
            <label key={`station${i + 1}`}>
            <Input              
              type="checkbox"
              value={`s${i+1}`}
              checked={checked}
              onChange={(e)=>selectStations(e)}              
            />;

            {checked ? 
              <CheckedContainer>
                  {`s${i+1}`}
              </CheckedContainer>;            
            : 
              <UncheckedContainer>
                  {`Station ${i+1}`}
              </UncheckedContainer>;
            }


          </label>;
          )}
        )}
    </div>;
  )
}

export default Test;

Is there a way to simplify this code while still utilizing Styled Components?

Answer №1

To keep track of the checkbox state, store it in a variable and then pass it to the styled component like this:

<StyledComponent isChecked={isChecked} />

Next, in the styled component:

const StyledComponent = styled.input`

 color: ${props => props.isChecked ? '#fff' : '#000'};

`

Repeat the process for background-color and border styling.

Answer №2

Incorporating props into a styled-component allows for the utilization of sass nesting to target child elements.

const StylishCheckbox = styled.label`
  position: relative;
  input[type="checkbox"] {
    // add styles here
  }
  .inner-checkbox {
    color: ${props => props.checked ? "red" : "blue"};
    // add styles here
  }
`

const ItemList = props => {
  return props.list.map(item => (
    <StylishCheckbox key={item.id} checked={item.checked}>
      <input checked={item.checked} type="checkbox" onChange={this.updateState} />
      <div className="inner-checkbox" />
    </StylishCheckbox>
  ))
}

I also recommend against creating styled components within another component.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Discover the method for obtaining a selected element in a bootstrap dropdown that is dynamically populated

Similar to the question asked on Stack Overflow about how to display the selected item in a Bootstrap button dropdown title, the difference here is that the dropdown list is populated through an ajax response. The issue arises when trying to handle click ...

CSS causing black bars to appear when image is moved

I recently started working with HTML/CSS and JS, but I've encountered a small issue. I'm using the bootstrap carousel and it's functioning well, but when I try to move the image higher up, black bars appear at the bottom as if my images are ...

"Exploring the new features of Node.js 14 with ECMAScript modules

When exploring Node's official documentation regarding its built-in support for ECMAScript modules, it is mentioned that There are different types of specifiers: ... Bare specifiers such as 'some-package' or 'some-package/shuffle&apo ...

What is the process for adding my JSON data to a select dropdown list?

Looking to populate a selectlist in HTML with options retrieved from an API. Below is the HTML code : <div id="example" role="application"> <div class="demo-section k-header"> <select id="FeaturesSelec ...

I would like to mention a website without inserting a direct hyperlink, for example, in the Safari browser

Is there a way to prevent a website name from becoming a clickable link in Safari? In my marketing email, I am highlighting the websites of both my client and their competitor. When mentioning the competitor's site "sitename.com," I want to avoid cre ...

Is there a more efficient alternative to `[].push.apply(this, arr)` for combining elements in an array instance within a constructor?

It only takes 0.15ms for this line in my constructor function to execute. [].push.apply(this, selector); I'm not satisfied with the 0.15ms execution time. I believe there must be a quicker alternative available. This particular line seems to be conv ...

Automated Copy and Paste Feature - JavaScript using Ajax

I am working on a unique auto-increment IMDB ID grabber that retrieves the ID as you type the name of a TV show. Currently, I have managed to create functionality where it checks if the field is empty; if not, it displays a button that directs you to a pag ...

What is the maximum allowable size for scripts with the type text/json?

I have been attempting to load a JSON string within a script tag with the type text/json, which will be extracted in JavaScript using the script tag Id and converted into a JavaScript Object. In certain scenarios, when dealing with very large data sizes, ...

Comparison of Static Site Generation (SSG) with Server-Side Rendering and Client-Side Rendering

The lack of concrete information surrounding the inner workings of Client-Side Rendering (CSR), Server-Side Rendering (SSR), and Static Site Generation (SSG) is truly perplexing to me. Despite numerous articles that vaguely touch on these concepts, I have ...

Managing JSON data retrieval and manipulation with REST API in Node.js and MongoDB

My technology stack includes Node.js and MongoDB with a rest api. The input data I'm dealing with looks like this: var doc={"name":"ABX", duedate : new Date() } Before sending it to the server, I stringify the data: /rest/update?doc=JSON.s ...

Warning: React Hook useEffect is missing a dependency in its dependency array when the dependencies are empty

As I work on cleaning up the warnings in my DOM, I've noticed an issue with every useEffect where the dependencies are set as []. An error message pops up stating that the useEffect has a missing dependency. My intention is to have the effect triggere ...

Exploring the capabilities of utilizing getServerSession in Next.js 13 along with API routes located in the

I am utilizing next-auth and attempting to obtain serverSession on a server component. I am using Next.js 13 beta with the App directory and the API directory located within the App directory. As per the next-auth documentation, this is the method recommen ...

How can the size of the font in a <div> be adjusted based on the number of characters present?

I am attempting to create a basic HTML and CSS layout with two div blocks, each 1000px wide, within a parent container that is 3000px wide. <div class="blocks"> <div class="block-a">text 1</div> <div class="block-b">text 2& ...

Erase a set of characters with the press of the backspace key (JavaScript)

Within my textarea, I have lines that start with a number and a period: <textarea autoFocus id="text-area"wrap="hard" defaultValue ={this.state.textAreaVal} onKeyUp={this._editTextArea}/> For example: Line 1 Line 2 Line 3 I've created a ...

Adjust the log level on winston in real-time

Is there a way to update the log level dynamically in winston and have it reflect across multiple files? I am facing an issue where changing the logger level in index.js does not affect readfile.js. How can I resolve this? Below is the code snippet: win ...

Display a tooltip when the user hovers over the column name of a BootstrapVue table

I am currently working with a bootstrap-vue table that has the following structure; https://i.sstatic.net/bfS9u.png Below is the code for setting up the table; <template> <div> <b-table striped hover :items="items" :fields= ...

Order of flexbox items when placed within separate divs?

Looking to rearrange the order of items using flexbox, but hitting a roadblock because one of the items I want to reorder is in a different div and not a direct child of the same parent as the other items. <div class="wrapper"> <div class="some ...

I am experiencing problems with invalidating queries following a mutation

Body: In my React project, I'm handling money transfer operations using React Query for data fetching and state management. One issue I'm facing is that the query does not invalidate after a successful transaction, except if I manually invalidat ...

Focusing solely on a particular category in EJS

I am struggling with this code snippet. HTML: <header<% if ( current.source === 'features' || current.path[0] === 'index' || current.source !== 'customers' ) { %> class="header-white"<% } %>> <div cl ...

Disable or set input text to read-only in Internet Explorer 9 and earlier versions using JavaScript or jQuery

Can anyone offer any suggestions on how to accomplish this task? I attempted using JavaScript with the code below, but it did not yield the desired results. element.readOnly="true"; element.readonly="readonly"; element.disabled="disabled"; I also tried ...