javascript - 如何使用 Headless UI 折叠 sibling

标签 javascript reactjs headless-ui

为了使用 Headless UI 制作 Accordion 组件,我使用了 Disclosure 组件。但是我有一个问题来控制它的 sibling 的折叠/展开状态。

所以,我想在打开一个时关闭其他兄弟,但 Disclosure 组件仅支持内部渲染 Prop ,打开和关闭。所以,我无法在组件外控制它,也无法在打开一个时关闭其他组件。

import { Disclosure } from '@headlessui/react'
import { ChevronUpIcon } from '@heroicons/react/solid'

export default function Example() {
  return (
    <div className="w-full px-4 pt-16">
      <div className="mx-auto w-full max-w-md rounded-2xl bg-white p-2">
        <Disclosure>
          {({ open }) => (
            <>
              <Disclosure.Button className="flex w-full justify-between rounded-lg bg-purple-100 px-4 py-2 text-left text-sm font-medium text-purple-900 hover:bg-purple-200 focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75">
                <span>What is your refund policy?</span>
                <ChevronUpIcon
                  className={`${
                    open ? 'rotate-180 transform' : ''
                  } h-5 w-5 text-purple-500`}
                />
              </Disclosure.Button>
              <Disclosure.Panel className="px-4 pt-4 pb-2 text-sm text-gray-500">
                If you're unhappy with your purchase for any reason, email us
                within 90 days and we'll refund you in full, no questions asked.
              </Disclosure.Panel>
            </>
          )}
        </Disclosure>
        <Disclosure as="div" className="mt-2">
          {({ open }) => (
            <>
              <Disclosure.Button className="flex w-full justify-between rounded-lg bg-purple-100 px-4 py-2 text-left text-sm font-medium text-purple-900 hover:bg-purple-200 focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75">
                <span>Do you offer technical support?</span>
                <ChevronUpIcon
                  className={`${
                    open ? 'rotate-180 transform' : ''
                  } h-5 w-5 text-purple-500`}
                />
              </Disclosure.Button>
              <Disclosure.Panel className="px-4 pt-4 pb-2 text-sm text-gray-500">
                No.
              </Disclosure.Panel>
            </>
          )}
        </Disclosure>
      </div>
    </div>
  )
}

我们如何控制组件外部的关闭/打开状态?

最佳答案

我认为使用 HeadlessUI 是不可能的,尽管您可以创建自己的 Disclosure 组件。

  • 通过创建存储有关披露的所有信息的 disclosures 状态将状态提升到父组件。
  • 使用 map 循环披露并呈现它们。
  • 呈现一个按钮,用于切换披露的 isClose 属性并处理 aria 属性。
  • 单击按钮时,切换所单击披露项的 isOpen 值并关闭所有其他披露项。

检查下面的片段:

import React, { useState } from "react";
import { ChevronUpIcon } from "@heroicons/react/solid";

export default function Example() {
  const [disclosures, setDisclosures] = useState([
    {
      id: "disclosure-panel-1",
      isOpen: false,
      buttonText: "What is your refund policy?",
      panelText:
        "If you're unhappy with your purchase for any reason, email us within 90 days and we'll refund you in full, no questions asked."
    },
    {
      id: "disclosure-panel-2",
      isOpen: false,
      buttonText: "Do you offer technical support?",
      panelText: "No."
    }
  ]);

  const handleClick = (id) => {
    setDisclosures(
      disclosures.map((d) =>
        d.id === id ? { ...d, isOpen: !d.isOpen } : { ...d, isOpen: false }
      )
    );
  };

  return (
    <div className="w-full px-4 pt-16">
      <div className="mx-auto w-full max-w-md rounded-2xl bg-white p-2 space-y-2">
        {disclosures.map(({ id, isOpen, buttonText, panelText }) => (
          <React.Fragment key={id}>
            <button
              className="flex w-full justify-between rounded-lg bg-purple-100 px-4 py-2 text-left text-sm font-medium text-purple-900 hover:bg-purple-200 focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75"
              onClick={() => handleClick(id)}
              aria-expanded={isOpen}
              {...(isOpen && { "aria-controls": id })}
            >
              {buttonText}
              <ChevronUpIcon
                className={`${
                  isOpen ? "rotate-180 transform" : ""
                } h-5 w-5 text-purple-500`}
              />
            </button>
            {isOpen && (
              <div className="px-4 pt-4 pb-2 text-sm text-gray-500">
                {panelText}
              </div>
            )}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

关于javascript - 如何使用 Headless UI 折叠 sibling ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72237519/

相关文章:

javascript - 如何发送像表单数据 postman 这样的值 - React js

reactjs - 如何在组合框 headless-ui 中设置默认选定选项?

javascript - 移动 chrome 和模式的奇怪行为

next.js - 如何将 Tailwind UI (headless ui) 组件与 Next JS 服务器组件一起使用?

javascript - 在 JavaScript 中,是否可以在 IE 上注册一个事件监听器来捕获页面上的所有更改、焦点和模糊事件?

javascript - 在react-router路由中使splat可选

javascript - 如何保证网页打开时元素在 View 中?

javascript - Backbone 与 Rails 中的模型混搭同步

javascript - 警告 :Invalid value for prop `data-callback` on <div> tag. 要么将其从元素中删除,要么传递一个字符串或数字值以将其保留在 DOM 中

javascript - ReactJS i18n 重新加载页面