定制手风琴的设计

Design of a custom accordion

我正在尝试用这些连接 parent 和 children 的精美红线设计一个自定义手风琴(见图)。

我在这里使用 Grommet 组件,但总而言之,布局只是一堆 divs(Box 标签)和一个用于 children(Collapsible 标签)的可折叠面板组件. Children 面板可以打开并显示更多内容。

经过几次尝试,我连接 parent 和 children 的方法是用 left-border 包裹外框,然后使用它上面的一个白框(第二个示例代码的 Stack 标签)。连接卡片和 left-border 的水平线只是样式 div 放置在 Child 选项卡旁边(在 SubMenuElement 组件内)。

我认为这是一个相当复杂的解决方案(也是因为我需要使白框响应)但我想不出更简单的解决方案。 您对我如何改进或 re-do 红色连接有什么建议吗? 先谢谢您的帮助! 请注意,我知道所有面板在点击时都使用相同的变量

 <MenuButton
    open={openMenu}
    label="PARENT TAB-XYZ"
    onClick={() => {
      const newOpenMenu = !openMenu;
      setOpenMenu(newOpenMenu);
      setOpenSubmenu1(!newOpenMenu ? false : openSubmenu1);
    }}
  />
  <Collapsible open={openMenu}>
    <Box background="antiquewhite" margin={{ left: 'small' }} border={{ side: 'left', size: '2px', color: 'red' }}>
      {Tabs.map(el => {
        return (
          <SubMenuElement
            key={el.title}
            open={openSubmenu1}
            label={el.title}
            onClick={() => setOpenSubmenu1(!openSubmenu1)}
          />
        );
      })}
    </Box>
  </Collapsible>

 <MenuButton
    open={openMenu}
    label="PARENT TAB-POU"
    onClick={() => {
      const newOpenMenu = !openMenu;
      setOpenMenu(newOpenMenu);
      setOpenSubmenu1(!newOpenMenu ? false : openSubmenu1);
    }}
  />
  <Collapsible open={openMenu}>
    <Stack anchor="bottom-left">
      <Box
        background="antiquewhite"
        margin={{ left: 'small' }}
        border={{ side: 'left', size: '2px', color: 'red' }}
      >
        {Tabs.map(el => {
          return (
            <SubMenuElement
              key={el.title}
              open={openSubmenu1}
              label={el.title}
              onClick={() => setOpenSubmenu1(!openSubmenu1)}
            />
          );
        })}
      </Box>
      <Box background="white" height="39px" width="35px"></Box>
    </Stack>
  </Collapsible>
</Box>

);

基于, I can propose you something like that: repro on Stackblitz

您会在第一个 link 上找到原始分频器代码。根据您的需要,我对其进行了一些修改,因此只需在内容左侧添加 link 即可。内容包装器上仍然有一个左边框,这对我来说似乎是最简单的解决方案。

您的主文件:

import React, { Component } from "react";
import { render } from "react-dom";
import Divider from "./divider";
import "./style.css";

const App = () => {
  const toggleAccordion = e => {
    e.target.classList.toggle("hidden");
  };

  return (
    <>
      <div className="accordion hidden" onClick={toggleAccordion}>
        accordion header
        <div className="accordion-content-wrapper">
          <Divider>
            <div>Content</div>
          </Divider>
          <Divider>
            <div>Content</div>
          </Divider>
          <Divider>
            <div>Content</div>
          </Divider>
        </div>
      </div>
    </>
  );
};

render(<App />, document.getElementById("root"));

我的手风琴css(我猜你的组件已经有这个功能,我只是做了一个最小的复制):

.accordion.hidden {
  height: 18px;
  overflow: hidden;
}

.accordion-content-wrapper{
  margin-left: 10px;
  border-left: 1px solid black;
}

对于分隔符,与我原来的答案没有太大变化,这里是代码:

import React from 'react';

const Divider = ({ children }) => {
  return (
    <div className="divider-component">
      <div className="container">
        <div className="border" />
        <span className="content">{children}</span>
      </div>
    </div>
  );
};

export default Divider;

css:

.divider-component .container{
  display: flex;
  align-items: center;
}

.divider-component .border{
  border-bottom: 1px solid black;
  width: 15px;
}

.divider-component .content {
  width: 100%;
}

即使您必须对其进行编辑以满足您的需要,我们的想法是添加一个 flex 容器,以便您可以在内容左侧添加小 link,与您的内容正确对齐.

对于遇到相同问题的人,我最终在 div 中使用了两个 50% 高度的 flexboxes 来替换水平线。这允许自动管理响应式调整大小,同时在最后一个项目边框上提供灵活性。

    const SubMenuElement = ({ last, label, open, onClick }: { last?: boolean; label: string; open: any; onClick: any }) => {
  return (
    <Box direction="row">
      <Line last={last} />
      <Box width="100%" margin={{ vertical: 'small' }}>
        <Card background="white" onClick={onClick}>
          ....
        </Card>
      </Box>
    </Box>
  );
};

线在哪里

   const Line = ({ last }: { last?: boolean }) => (
  <Box direction="column" width="20px" flex="grow">
    <Box height="50%" style={{ borderLeft: '1px solid red', borderBottom: '1px solid red' }} />
    <Box height="50%" style={last ? {} : { borderLeft: '1px solid red' }} />
  </Box>
);