如何在React折叠面板中通过CSS Transform实现点击切换图标及背景色?
解决方案
1. 传递激活状态到样式组件
首先需要把组件内的isActive状态传递给Title、Icon和Content样式组件,让样式能根据状态动态调整:
修改后的React组件代码:
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={color}> <Styled.Title onClick={() => setIsActive(!isActive)} color={isActive ? activeColor : color} isActive={isActive} > {text} <Styled.Icon color={isActive ? activeColor : color} isActive={isActive} > <Icon name={icon}/> </Styled.Icon> </Styled.Title> {isActive && ( <Styled.Content color={isActive ? activeColor : color} isActive={isActive} > {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: "grey", activeColor: "primary", } export default Accordion
2. 实现图标旋转切换
在Icon样式组件中,通过transform结合isActive状态实现旋转效果,同时添加过渡动画让切换更平滑:
修改样式代码中的Icon部分:
export const Icon = styled.div` display: flex; align-items: center; width: auto; height: auto; transition: transform 0.3s ease-in-out; /* 可根据需求调整旋转角度,比如180度 */ transform: ${({ isActive }) => isActive ? 'rotate(90deg)' : 'rotate(0deg)'}; `
3. 修正背景色与文字颜色的显示问题
你当前代码中文字颜色和背景色使用了同一个主题色值,导致文字无法看清。需要区分两者的颜色逻辑,比如背景色用指定主题色,文字用对比色:
修改Title和Content的样式:
export const Title = styled.div` width: auto; height: auto; display: inline-flex; gap: 161px; border-radius: 10px 10px 0px 0px; padding: 10px 10px 10px 10px; cursor: pointer; /* 文字用对比色 */ color: ${({ color, theme }) => { switch (color) { case "grey": return theme.colors.white; case "neutrals": return theme.colors.neutrals[900]; case "primary": return theme.colors.white; default: return theme.colors.white; }; }}; /* 背景用指定主题色 */ background-color: ${({ color, theme }) => { switch (color) { case "grey": return theme.colors.grey[600]; case "neutrals": return theme.colors.neutrals[100]; case "primary": return theme.colors.primary[500]; default: return theme.colors.grey[600]; } }}; transition: background-color 0.3s ease; ` 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 10px 10px 10px; /* 文字用对比色 */ color: ${({ color, theme }) => { switch (color) { case "grey": return theme.colors.white; case "neutrals": return theme.colors.neutrals[900]; case "primary": return theme.colors.white; default: return theme.colors.white; } }}; /* 背景用指定主题色,可略浅于Title背景 */ background-color: ${({ color, theme }) => { switch (color) { case "grey": return theme.colors.grey[500]; case "neutrals": return theme.colors.neutrals[200]; case "primary": return theme.colors.primary[400]; default: return theme.colors.grey[500]; } }}; transition: background-color 0.3s ease; `
4. 额外优化建议
为Content添加展开/收起的高度过渡动画,避免突然显示/隐藏:
export const Content = styled.div` /* 保留原有样式 */ max-height: ${({ isActive }) => isActive ? '1000px' : '0'}; overflow: hidden; transition: max-height 0.3s ease; `
注意:添加此动画后,需要去掉原有的{isActive && ...}条件渲染,直接渲染Content组件,通过max-height控制显示。
内容的提问来源于stack exchange,提问作者Emilia
相关产品推荐
相关产品推荐

