You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于激活状态更改Styled Components颜色?React手风琴样式调整

解决方案:React手风琴组件激活状态样式切换(Emotion Styled)

我来帮你搞定这个手风琴组件的样式切换问题,咱们一步步调整,实现展开时黑底白字的效果:

1. 修正Styled组件的样式逻辑

你已经通过isActive状态控制了属性传递,但目前Emotion组件的样式没有正确和传入的color/activeColor以及主题绑定。我们先重构样式文件,让它能根据状态切换颜色:

import styled from "@emotion/styled"

// 抽个辅助函数,统一处理文字颜色逻辑
const getTextColor = (props) => {
  const targetColor = props.isActive ? props.activeColor : props.color;
  return props.theme[targetColor];
}

// 处理背景色,激活时用黑色,非激活时用主题grey
const getBgColor = (props) => {
  return props.isActive ? props.theme.black || "#000" : props.theme.grey;
}

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: ${getTextColor};
 background-color: ${getBgColor};
 cursor: pointer; /* 加上指针提示,提升交互感 */
`

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.isActive ? props.theme.white || "#fff" : props.theme.neutrals};
 background-color: ${getBgColor};
`

export const Icon = styled.div`
 display: flex;
 align-items: flex-start;
 width: auto;
 height: auto;
 color: ${getTextColor}; /* 图标颜色跟着文字走 */
`

2. 调整React组件的属性传递

现在需要把isActive状态和颜色属性一起传递给所有Styled组件,同时修复图标切换的重复代码问题:

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, text, button, color, activeColor }) =>  {
  const [isActive, setIsActive] = useState(false);
  
  // 把状态和颜色属性打包,避免重复传递
  const sharedStyleProps = { isActive, color, activeColor };

  return (
    <Styled.Accordion>
      <Styled.Title 
        onClick={() => setIsActive(!isActive)}
        {...sharedStyleProps}
      > 
        {text}
        <Styled.Icon {...sharedStyleProps}>
          {/* 根据状态切换图标,之前重复写了两个icon属性,这里修正 */}
          <Icon name={isActive ? "arrowUp" : "arrowDown"}/>
        </Styled.Icon> 
      </Styled.Title>
      {isActive && (
        <Styled.Content
          {...sharedStyleProps}
        >
          {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", "white"]), // 新增white选项
}

Accordion.defaultProps = {
  children: null,
  icon: null,
  name: null,
  button: null,
  color: "neutrals",
  activeColor: "white", // 默认激活时文字用白色
}

export default Accordion

3. Storybook配置优化

修正Story里的重复icon属性,同时添加颜色控制选项,方便在Storybook里预览不同状态:

import { Canvas, Story } from "@storybook/react";
import Accordion from "./Accordion";
import Button from "../Button";

export const TemplateGrid = (args) => (
  <div>
    <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>
    <Accordion {...args}>
      <p>Odpowiedz</p>
    </Accordion>
  </div>
)

export default {
  title: "Components/Accordion",
  component: Accordion,
  argTypes: {
    color: {
      control: "select",
      options: ["primary", "neutrals", "grey"],
    },
    activeColor: {
      control: "select",
      options: ["primary", "neutrals", "grey", "white"],
    },
  },
};

<Canvas>
  <Story
    name="Overview - black with button"
    args={{
      text: "Fundacja",
      button: (
        <Button
          text="Button ->"
          variant="textLine"
          size="small"
          href="https://google.com"
        />
      ),
      color: "neutrals",
      activeColor: "white",
    }}
  >
    {TextTemplate.bind()}
  </Story>
</Canvas>

关键注意点

  • 主题色检查:确保你的Emotion主题配置里包含black和white,如果没有,可以直接用#000和#fff代替主题变量。
  • 状态统一传递:用sharedStyleProps打包状态和颜色属性,减少重复代码,让组件更易维护。
  • 交互细节:给Title加上cursor: pointer,让用户知道这个区域是可点击的。

内容的提问来源于stack exchange,提问作者Emilia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 17:15:51