What is the best way to choose a parent component's variant using styled components?

When using styled-components, we have the ability to add contextual styles utilizing the component selector pattern. But how can we target specific parent variants to style a child component contextually? In this scenario, we have three components - Child, NoteWrapper, and Note.

const Child = styled.div<{ editing?: boolean }>`
  ${props => props.editing && css`some styles`}
`

const NoteWrapper = styled.div<{ compact?: boolean }>`
  ${props => props.compact && css`some styles`}
`

const Note = styled.input`

/* How can I style this when Child is editing and NoteWrapper is compact */

`

const App = () => {
  return (
   <Child editing>
    <NoteWrapper compact>
     <Note/>
    </NoteWrapper>
   </Child>
  )
}

`

In traditional CSS, we could achieve something similar to the following:


.child.editing .note-wrapper.compact .note {
  /* Contextual styles would go here */
}

While it's possible to easily pass the editing and compact variables to the Note component, doing so becomes cumbersome with highly nested components.

So, my query is: how do I apply styles to Note when Child is in an editing state and NoteWrapper is compact within the styled-components selector pattern?

I'm not sure if there is a built-in way to accomplish this in styled-components. Is there?

const Note = styled.input`
 ${Child.editingClass} ${NoteWrapper.compactClass} & {
  /* Insert contextual styles here */
 }
`

Answer №1

From my understanding, accessing editing or compact directly in CSS is not possible as they are props and do not propagate in CSS. However, the same outcome can be achieved using classes or data attributes.

Here's a way to achieve it:

const App = () => {
  return (
  <Child data-editing={true}>
    <NoteWrapper data-compact={true}>
      <Note/>
    </NoteWrapper>
  </Child>
  )
}

const Child = styled.div`
`

const NoteWrapper = styled.div`
`

const Note = styled.input`
  ${Child}[data-editing="true"] ${NoteWrapper}[data-compact="true"] & {
    /* 
      Styles applied only when Child is editing and NoteWrapper is compact
    */
    color: red;
  }

`

It's important for styled-components to generate valid CSS. The placeholder ${Child} will be substituted with a custom-generated classname like .sc-abc123, resulting in valid CSS such as

.sc-abc123[data-editing="true"]
.

An alternative approach using classes could look like this:

const App = () => {
  return (
  <Child className="editing">
    <NoteWrapper className="compact">
      <Note/>
    </NoteWrapper>
  </Child>
  )
}

const Child = styled.div`
`

const NoteWrapper = styled.div`
`

const Note = styled.input`
  ${Child}.editing ${NoteWrapper}.compact & {
    /* 
      Styles applied only when Child is editing and NoteWrapper is compact
    */
    color: red;
  }

`

I personally prefer data-attributes because it clearly indicates their purpose is logical rather than being tied to specific styles like in the case of using classes. However, both methods function equally well in terms of functionality :)

Answer №2

Another option is to send the properties directly to the Note element and implement a comparable logic check.

<Note
  editCompact={editMode && compactView}
/>

const Note = styled.div`
  ${props =>
    props.editCompact
      ? css`color: yellow;`
      : css`color: green;`
    };
`;

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

Encountered an error while attempting to load module script: seeking assistance

index-d5Zm7UFq.js:1 Encounter Failed to load module script issue: The server returned a MIME type of "text/html" instead of the expected JavaScript module script. Strict MIME type checking is enforced for module scripts according to the HTML specification. ...

Retrieve query parameters during an asynchronous call using react-redux

In my React Redux project (version 4.4.5), I am utilizing react-router-redux (version 4.0.5) and redux-async-connect (version 0.1.13). Prior to loading my container component, I need to asynchronously fetch data from my API. The API endpoint includes a que ...

How can the hreflang tag be used correctly in a React application that supports multiple languages?

I have a React application with 3 pages(routes) and I support 2 languages (English and Spanish). Should I insert the following code into the <head></head> section of the public\index.html file like this? <link rel="alternate" ...

Dealing with timing errors in React when making a POST request

My current setup involves a React file connected to an Express/Node backend and SQL database. The backend functionalities are working as expected, with all routes tested and verified using Postman. The application can successfully handle GET, POST, UPDATE, ...

php failed to send values to ajax, experiencing an error

To test if everything is working correctly, I am attempting to send a value from AJAX to PHP and retrieve it. However, when I click on a button to run the test, an error occurs and 'Failed' alert pops up. How can I resolve this issue to achieve s ...

Exploring the Depths of Facebox Lightbox with JavaScript

I encountered a strange issue while working on my rails app. I am utilizing jQuery and the Facebox Lightbox for popup forms, and I wanted to incorporate some jQuery validation into the form. Strangely, when I attempted to implement this, I faced unexpected ...

Issues with the card display within a Bootstrap carousel

Having encountered challenges with displaying cards in a bootstrap carousel, I am seeking assistance. To view my current (incomplete) project, please refer to the CodePen link below. https://codepen.io/robbiecorcoran/pen/eYMVvEN <!-- SEEKING ASSISTANCE ...

What causes this element to give the appearance of scrolling even though it is set to position fixed?

I've been grappling with this issue for quite some time. On my webpage, there is an element with a style of position:fixed;. It's set to top:0; and left:0;. However, when you scroll down the page, it does not stay fixed in position. Interestingl ...

React - Incorrect use of hooks and class components

Understanding hooks as the opposite of a class component can be confusing. A simple line of code can trigger an error when trying to adapt it for use in a class component. Take, for example, this situation: .jsx files and functional components work seamles ...

Error in cloned selections with bootstrap-selectpicker showing one less item

When duplicating a bootstrap-select dropdown, the duplicate dropdown appears to be offsetting selections by 1. For example, if the second option is clicked, the first one is actually selected. Here is an illustration: If "New Castle" is clicked in the ...

Is it beneficial to cater to users who do not have JavaScript capabilities on my website, considering that I am currently using JS links to

My website heavily relies on JavaScript for navigation, passing a parameter to always indicate the starting page and displaying it in a navbox for easy access back. Should I include both href links for non-JS versions and onclick links for JS-enabled vers ...

"The seamless integration of Ubergallery with AJAX functionality creates a

When I attempted to access the Ubergallery through an Ajax call, I encountered numerous issues that I was able to resolve using the script provided below. However, despite resolving most of the problems, I am now facing a new issue - the navigation buttons ...

Is it possible that a declaration file for module 'material-ui/styles/MuiThemeProvider' is missing?

I have been trying to implement the react material-ui theme after installing it via npm. However, I am encountering errors when adding 'import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";' in boot-client.tsx: TS7016: Could not ...

Ways to eliminate header and footer data while printing a webpage

In my attempt to implement the code displayed below, I am encountering an issue where the header and footer continue to appear on the printed page. Despite numerous attempts with various CSS elements, I have been unsuccessful in removing the header and fo ...

validate the existence of the username upon submission of the form

Here is some code that I have written. .js $(document).ready(function() { $("#username").focusout(function() { $.ajax({ type:'post', url:site_url()+'/client/checkUserName', data:{&apos ...

Steps for displaying a loading gif animation prior to retrieving text content using JavaScript

Before fetching the PHP result, I want a loading GIF image to display within the div section. <!DOCTYPE html> <html> <head> <title> CTR Calculator Tool | Free Click Through Rate Online Calculator </title> & ...

How to import a module from the root path using TypeScript in IntelliJ IDEA

Despite this topic being widely discussed, I still struggle to understand it. Below is my tsconfig.json file: { "compilerOptions": { "module": "commonjs", "target": "es2017", "sourceMap": true, "declaration": true, "allowSyntheticDe ...

The selected jquery script is failing to function as intended

I'm currently implementing jQuery chosen in a select element to enhance user experience, however I'm facing an issue when attempting to copy the chosen div to another div using jQuery $(document).ready(function() { $(".chosen").chosen({}); ...

Navigating Gmail pop-up windows can be tricky. Take a look at the

Looking for tips on dealing with Gmail popups? Check out the screenshot below. https://i.sstatic.net/5m1OK.png ...

Tips for refreshing Facebook's og tags

I've been racking my brains over this issue for days, and despite the abundance of similar inquiries, I have yet to find a solution. On my blog-like website, each post requires its own title and description for Facebook articles. I know I can set the ...