如何基于激活状态更改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
相关产品推荐
相关产品推荐

