How can I update the color scheme in styled components based on the active state of the component?

I'm currently working on a react accordion component that requires changing styles based on the active and inactive states. I have successfully set the state and added two props for color and active color. The goal is to change colors when the user clicks on the title div. While I have added conditions in JSX, I am unsure how to properly style it using styled components. I have defined themes for colors like "primary", "neutrals", and "grey" while also utilizing storybook to display them with default values. Below is the code snippet of my react component:

import { string, node, oneOf, bool } from "prop-types"
import * as Styled from "./Accordion.styled"
import Icon from "design-system/components/icon"
import React, { useState } from 'react'
const Accordion = ({ children, icon, text, button,
  color, activeColor, }) =>  {
  const [isActive, setIsActive] = useState(false);
  return (
  <Styled.Accordion
  color={isActive ? activeColor : color}
  >
    <Styled.Title  onClick={() => setIsActive(!isActive)}
    color={isActive ? activeColor : color}
    > {text}
    <Styled.Icon color={color}>
    <Icon name={icon}/>
    </Styled.Icon> 
    </Styled.Title>
    {isActive &&
    <Styled.Content
    color={isActive ? activeColor : color} >
    {children} 
    {button}
    </Styled.Content>
    }
  </Styled.Accordion>
);
}
Accordion.propTypes = {
  text: string.isRequired,
  children: node.isRequired,
  icon: string,
  name: string,
  button: node,
  color: oneOf(["primary", "neutrals", "grey"]),
  activeColor: oneOf(["primary", "neutrals", "grey"]),
}
Accordion.defaultProps = {
  children: null,
  icon: null,
  name: null,
  button: null,
  color: "neutrals",
  activeColor: "neutrals",
}
export default Accordion

import styled from "@emotion/styled"
import { css } from "@emotion/react"

export const Accordion = styled.div`
 display: flex;
 text-decoration: none;
 width: auto;
 height: auto;
 flex-direction: column;
 align-items: flex-start;
 justify-content: start;
 border-radius: 30px;
 `
export const Title = styled.div`
  width: auto;
  height: auto;
  display: inline-flex;
  gap: 161px;
  border-radius: 10px 10px 0px 0px;
  padding: 10px 0px 0px 10px;
  color: ${props => props.theme.primary};
  background-color: ${props => props.theme.grey};
`

export const Content = styled.div`
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: start;
  width: auto;
  height: auto;
  border-radius: 0px 0px 10px 10px;
  padding: 10px 100px 0px 10px;
  color: ${props => props.theme.neutrals};
  background-color: ${props => props.theme.grey}
`

  export const Icon = styled.div`
  display: flex;
  align-items: flex-start;
  width: auto;
  height: auto;
  `

And here is the layout from storybook:

<Canvas>
  <Story
    name="Overview - black with button"
    args={{
      icon: "arrowDown",
      icon: "arrowUp",
      text: "Fundacja",
      button: (
        <Button
          text="Button ->"
          variant="textLine"
          size="small"
          href="https://google.com"
        />
      ),
    }}
  >
    {TextTemplate.bind()}
  </Story>
</Canvas>
export const TemplateGrid = (args) => (
 <div
    style={{
    }}
  >
  <Accordion {...args}>
      <div>
      <div>O nas</div>
      <div>Aktualności</div>
      <div>Opinie</div>
      <div>Partnerzy</div>
      <div>Umowa</div>
      </div>
    </Accordion>
  </div>
)
export const TextTemplate = (args) => (
  <div
    style={{
    }}
  >
  <Accordion {...args}>
      <p>
          Odpowiedz
      </p>
    </Accordion>
  </div>
)
Here are images showing how those layouts look: [![Layout Image 1][1]][1] [![Layout Image 2][2]][2] [![Layout Image 3][3]][3] [![Layout Image 4][4]][4] I aim to switch the colors so that when unhiden, they have a black background and white font. Can you assist in achieving this design change?

Answer №1

Instead of using your exact example, I utilized sample components to illustrate the concept. By incorporating ternary operations in styled-components, you can dynamically change the color based on the state.

For instance, consider the following styled component for a h1:

const StyledText = styled.h1`
  color: ${(props) => (props.color ? props.color : 'gray')};
`;

In this component, the color will be displayed if the color prop is present, otherwise it defaults to gray (or any preferred theme color). The complete component looks like this:

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

const StyledText = styled.h1`
  color: ${(props) => (props.color ? props.color : 'gray')};
`;

const Text = ({ children, activeColor, regularColor }) => {
  const [isActive, setIsActive] = useState(false);

  const handleClick = () => {
    setIsActive(!isActive);
  };

  return (
    <div>
      <StyledText color={isActive ? activeColor : regularColor}>
        {children}
      </StyledText>
      <button onClick={handleClick}>Change Active</button>
    </div>
  );
};

export default Text;

I included a handleClick function that toggles the activeState when the button is clicked. The color property of StyledText changes based on the activeState. If active, it shows the activeColor; otherwise, it displays the regularColor. In the parent component, I pass these colors as props. Here is an example of the parent component:

import Text from './components/Text';

function App() {
  return (
    <Text activeColor="#ff0000" regularColor="#F5F5DC">
      Hello World!
    </Text>
  );
}

export default App;

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

Learn the process of sending both Header and Body data in a POST request using Axios with Vue.js

I'm currently attempting to call the post API of AWS Cognito's Token endpoint. The API functions perfectly when tested in my Postman client, but I am encountering issues when implementing it in my VueJS code. Here is a snippet of my code: test. ...

Whenever the click event is triggered, Ajax is making numerous duplicate calls

Each time I click to fetch my content using an AJAX call, the calls end up duplicating themselves. I've tried various on-click events I came across on Stackoverflow threads, but unfortunately none of them seem to be solving the issue. $(document).rea ...

Serialize a series of select boxes to optimize for AJAX POST requests

To better explain my issue, let's consider a simple example: Imagine I have a form that collects information about a user: <form action="#" method="post" id="myform"> <input type="text" name="fname" /> <input type="text" name= ...

Please input the number backwards into the designated text field

In my react-native application, I have a TextInput where I need to enter numbers in a specific order such as 0.00 => 0.01 => 0.12 => 1.23 => 12.34 => 123.45 and so on with each text change. I tried using CSS Direction "rtl" but it didn' ...

How to make images invisible on mobile in Next.js without loading them

How can I efficiently prevent an image from being displayed when the screen width is less than 800px in next.js without causing it to be downloaded by the browser? Here are two potential solutions: Utilizing srcset and displaying a 1px image, as shown in ...

Customizing HTML list headers using an external JavaScript function

Hi everyone, I've been working on a login page and I want to enhance the user experience by displaying the logged-in user's username at the top of the screen, which can then trigger a dropdown list upon clicking. To achieve this, I've writt ...

What steps should I take to address both the issue of duplicate names and the malfunctioning fixtures?

There are issues with duplicate item names and the cache not updating immediately after running the script. Instead of fetching new data, it retrieves previous values from the last item shop sections. If the remove_duplicates function is not used, it displ ...

Different Ways to Access an Array in an EJS Template

After receiving a list of IDs from an API, I need to include them in a URL within an EJS template to retrieve the correct items. For example, the URL format is: Here are some example IDs: 526 876 929 The desired output inside the EJS template: <li&g ...

Local variables in AngularJS across multiple Angular applications

Looking for a method to retain a local variable not affected by path or angular app changes. Attempted using $window.localStorage.set and get item, rootScope, and $window.variable with no success. ...

What is preventing ShowViaLink() from functioning properly in Firefox and Internet Explorer?

I am facing an issue with my webpage where the navigation does not work on Firefox or IE, but it works perfectly fine on Chrome. I suspect that the problem lies in this code, as when I made changes to it, the navigation stopped working on Firefox & IE: ...

Issue: 0909006C - The PEM routines are unable to retrieve the name as there is no start line

Upon cloning a project to begin working on it, I encountered an error after running yarn install and yarn start https. The error message reads: Error: 0909006C:PEM routines:get_name:no start line... The project was created by someone else and unfortunatel ...

React-MobX issue: A boolean value is required for the 'decoratorsBeforeExport' option in the 'decorators' plugin

I encountered an error message stating: To migrate from Babylon/Babel 6 or utilize the old decorators proposal, it is recommended to use the 'decorators-legacy' plugin instead of 'decorators'. package.json "@babel/plugin-proposal-deco ...

Basic media query does not affect div resizing or font changes in Chrome or Internet Explorer

I am facing an issue with a simple media query that is not working as expected in Chrome or IE, but strangely it works fine in FF. I have tried various formulations of the media query without success. Any assistance would be greatly appreciated. Below is ...

Looking for solutions to issues with Style errors and Visibility problems?

< table border="1" cellpadding="0" cellspacing="0" width="100%"> < tr> < td>1< /td> < td>1< /td> < td>1< /td> < td>1< /td> < td>1< /td> ...

The Google Rich Result Testing Tool encountered an issue: Parsing error detected - a '}' or object member name is missing

Visit my website: www.bharatpharmatech.com I have implemented my code using Next.js Here is the schema I am utilizing: { "@context": "https://schema.org/", "@type": "WebSite", "name": "Bharat Pharmate ...

Utilizing Firebase login to integrate with Facebook API

My current setup involves Facebook authentication tied to login, all managed through Firebase. However, I now face the need to make an API call to Facebook using 'me/friends/' endpoint without having to send another request since I am already log ...

What is the method for enlarging an element without regard to surrounding elements?

I am working on a code where I want the element to zoom in when hovered, completely disregarding its normal flow. By "ignoring its flow," I mean that other elements like tags might obstruct parts of its content. https://i.sstatic.net/NBoez.png https:// ...

When positioned at high or low angles, the camera starts acting strangely

In my Three.js scene, I have a camera that I need to move and change its angle around a specific focal point. The focal point is actually the camera's position, and during rendering, I translate the camera by using the cameraBuff vector to position it ...

Misleading routes showing up as legitimate

I have been utilizing path variables within my Route components. Initially, I set it up like this: <Route path={"/:brand/"} component={HomeContainer} /> However, I noticed that incorrect URLs were being treated as valid. To address this issue, I mo ...

What is the best method to choose the initial offspring of the primary brother or sister within a list item?

Is there a way to specifically target the nested li elements in my css selector? Check out the Demo li:first-child { background-color: rgb(236, 236, 236); list-style-type: none; margin-bottom: 3px; padding: 8px; } <ul> <li& ...