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

React + TypeScript 手风琴过渡动画失效问题求助

React + TypeScript 手风琴组件过渡动画失效问题

问题详情

自定义手风琴组件时,展开/收起的内容过渡动画、图标切换动画均不生效,添加通用过渡样式后仍无改善。

相关代码

index.tsx

import { useState } from "react";
import { AccordionButton, AccordionContent, Wrapper } from "./styles";
import { AccordionProps } from "./interfaces";
import { BsChevronDown, BsChevronUp } from "react-icons/bs";

export default function Accordion({ title, text }: AccordionProps) {
  const [isOpen, setIsOpen] = useState(false);

  const handleClick = () => {
    setIsOpen(!isOpen);
    returnIcon();
  };

  const returnIcon = () => {
    return isOpen ? <BsChevronUp /> : <BsChevronDown />;
  };

  return (
    <Wrapper>
      <AccordionButton onClick={handleClick}>
        {title} {returnIcon()}
      </AccordionButton>

      <AccordionContent isOpen={isOpen}>
        <p>{text}</p>
      </AccordionContent>
    </Wrapper>
  );
}

styled-components 样式代码

import styled from "styled-components";
import { AccordionContentProps } from "./interfaces";

export const AccordionButton = styled.button`
  background-color: #606582;
  color: #ffffff;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.6s;
  &:hover {
    background-color: #60658295;
  }
  > svg {
    float: right;
  }
`;

export const AccordionContent = styled.div<AccordionContentProps>`
  display: ${(props) => (props.isOpen === false ? "none" : "block")};
  padding: 0 18px;
  background-color: white;
  overflow: hidden;
`;

export const Content = styled.div`
  padding: 10px 0px;
  flex-wrap: wrap;
  max-width: 750px;
  margin-right: auto;
  margin-left: auto;
  @media only screen and (max-width: 600px) {
    max-width: 80%;
  }
`;

export const Wrapper = styled.div`
  padding: 10px 0px;
`;

已尝试无效操作

添加以下过渡样式后问题未解决:

-webkit-transition: all 0.4s ease-in;
-moz-transition: all 0.4s ease-in;
-o-transition: all 0.4s ease-in;
transition: all 0.4s ease-in;

解决方案

1. 修复内容展开/收起动画

display: none 与 display: block 的切换无法触发过渡(无中间状态),改用高度变化实现动画:

修改 AccordionContent 样式:

export const AccordionContent = styled.div<AccordionContentProps>`
  padding: 0 18px;
  background-color: white;
  overflow: hidden;
  /* 用max-height实现自适应高度的过渡 */
  max-height: ${props => props.isOpen ? '1000px' : '0'};
  /* 同时过渡高度和内边距,避免内容突兀 */
  transition: max-height 0.4s ease-in-out, padding-top 0.4s ease-in-out, padding-bottom 0.4s ease-in-out;
  padding-top: ${props => props.isOpen ? '18px' : '0'};
  padding-bottom: ${props => props.isOpen ? '18px' : '0'};
`;

注:1000px 可根据实际内容高度调整,确保大于最大内容高度即可。

2. 修复图标切换动画

直接替换图标组件无法触发过渡,改用CSS旋转实现切换效果:

修改 index.tsx 代码

import { useState } from "react";
import { AccordionButton, AccordionContent, Wrapper } from "./styles";
import { AccordionProps } from "./interfaces";
import { BsChevronDown } from "react-icons/bs";

export default function Accordion({ title, text }: AccordionProps) {
  const [isOpen, setIsOpen] = useState(false);

  const handleClick = () => {
    setIsOpen(!isOpen);
  };

  return (
    <Wrapper>
      <AccordionButton onClick={handleClick}>
        {title} 
        {/* 单个图标,通过类名控制旋转 */}
        <BsChevronDown className={isOpen ? 'icon-rotated' : ''} />
      </AccordionButton>

      <AccordionContent isOpen={isOpen}>
        <p>{text}</p>
      </AccordionContent>
    </Wrapper>
  );
}

修改 AccordionButton 样式

export const AccordionButton = styled.button`
  background-color: #606582;
  color: #ffffff;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.6s;
  &:hover {
    background-color: #60658295;
  }
  > svg {
    float: right;
    /* 添加旋转过渡 */
    transition: transform 0.4s ease-in-out;
  }
  /* 旋转样式 */
  > .icon-rotated {
    transform: rotate(180deg);
  }
`;

3. 额外优化

  • 移除无用的 returnIcon 函数,简化逻辑
  • 确保 AccordionContentProps 中 isOpen 定义为布尔类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:05:29