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

With TypeScript, you have the flexibility to specify any data type in the generic types when using the axios.get method

axios.get('/api') When working with TypeScript as shown above, it is important to designate types for better clarity. This allows us to reference the type definition of axios, like so: (method) AxiosInstance.get<any, AxiosResponse<any> ...

Ways to modify client socket from JavaScript to PHP

Looking for a way to convert a client socket from JavaScript to PHP in order to receive data from the server socket? Check out the PHP socket Bloatless library here. This is an example of the Client Javascript code: <script> // connect to chat appl ...

"Material-UI enhanced React date picker for a modern and user-friendly

Currently, I am utilizing the Date picker feature from Material UI. The code snippet responsible for implementing it is as follows: import { DatePicker } from 'redux-form-material-ui'; <Field name="birthDate" ...

How can a user be assigned to a button in React in order to block them?

Within my user list, each user is accompanied by a block button. Upon clicking this button, a modal appears to confirm the blocking action for that specific user. Although I have set up the display of the modal, when I click on the confirm button, nothing ...

Choose specific items and move them to a different page

I'm currently working on developing an app and I've hit a roadblock when it comes to allowing users to select multiple images to be passed to another screen. Can anyone offer some guidance on how to accomplish this? Your help would be greatly app ...

Exploring the capabilities of X-grid within Material v5

I have been working on a React app using the latest v5 alpha version of material-ui. The documentation mentions that 'The data grid components support both v5 and v4'. However, when I tried to import X-grid, I encountered this error: ./node_mod ...

Encountered an issue while building npm: "Error: Unable to locate module @restart/context

Lately, I've encountered an issue with npm build after upgrading to the latest version of react-bootstrap (1.0.0-beta.6). While creating an optimized production build... Failed to compile. Module not found: '@restart/context/forwardRef'. P ...

Seeking information from the API server

Following a traditional structure, you will find a list of posts at /posts and a detailed view at /posts/1. When using an API server on the backend alongside React+Redux on the frontend, data is typically fetched upon reaching the /posts endpoint. However, ...

Ways to address postcss vulnerabilities in a create-react-app generated application

Approximately one month ago, I developed a new app using create-react-app. Recently, after running npm update, I received the following message: 80 moderate severity vulnerabilities To address issues that do not require attention, run: npm audit fix To ...

Is it possible to use Material-UI Link along with react-router-dom Link?

Incorporating these two elements: import Link from '@material-ui/core/Link'; import { Link } from 'react-router-dom'; Is there a method to combine the Material-UI style with the features of react-router-dom? ...

Customizing Ngx-bootstrap Carousel Indicator, Previous, and Next Button Styles

<carousel > <a href=""> <slide *ngFor="let slide of slides"> <img src="{{slide.imgUrl}}" alt="" style="display: block; width: 100%;"> </slide> 1. Is there a way to substitute the indicators with images ...

Align a component vertically in a FlexBox using Material UI

I have a React app where I created a card with specified min width and height, containing only a header. I want to add flexbox that occupies the entire left space with justify-content="center" and align-items="center". This way, when I insert a circular pr ...

Using Ajax without implementing JavaScript

Is it possible to develop an application that utilizes Ajax without relying on JavaScript, allowing it to function even if JavaScript is disabled by the user in their browser? Are there any restrictions or limitations to consider? ...

The tooltip in chart.js stubbornly holds onto past data even after it's been

Utilizing chart.js, I have implemented a feature where a tooltip displays when a user hovers over the chart successfully. However, I encountered an issue. I added an option for users to un-check data-points, which works correctly. But now, the tooltip fun ...

Tips for selecting siblings or children of intricate components in Material UI/JSS

In my current project, I am using Material UI which has been performing well. However, I am facing a challenge with styling child and sibling components using JSS. For instance, when Material UI's component is rendered, it appears like this: <div ...

"Revolutionize real-time data updates with Node.js, Redis, and Socket

Greetings! I am currently working on a project for my school that involves creating a "Twitter clone." My goal is to incorporate a publish subscribe pattern in order to facilitate real-time updates. One key feature users will have access to is the abili ...

Utilizing icons with vuetify's v-select component: a guide

In the code snippet below, I am using a v-select element to display a list of items filled from an array: <v-select v-model="myModel" :items="users" chips :readonly="!item.Active" label="Required users to f ...

Discover the row and column of a selected table cell using vanilla JavaScript, no need for jQuery

In my JavaScript code, I am currently working on creating an onclick function that will display the row and column of a specifically clicked cell in a table. I have successfully implemented functionality to return the column number when the cell is click ...

Unable to retrieve image

I want to save a Discord user's profile picture on Replit, but even though it downloads successfully, the image is not displaying. Here is the code I am using: const request = require('request') const fs = require('fs') app.get(&qu ...

What steps can I take to fix the Error with webpack's style hot loader JavaScript?

Just starting out with native script and encountered an issue when running this code: <template> <view class="container"> <text class="text-color-primary">My Vue Native Apps</text> </view> </template> &l ...