Para hacer el componente de acordeón con la interfaz de usuario sin cabeza, he usado el componente Disclosure. Pero tengo un problema para controlar el estado de colapso/expansión de sus hermanos.
Por lo tanto, quiero cerrar otros hermanos cuando abro uno, pero el componente Disclosure solo admite accesorios de representación internos, abrir y cerrar. Por lo tanto, no puedo controlarlo fuera del componente y no puedo cerrar otros cuando abro uno.
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> ) }¿Cómo controlamos el estado cerrado/abierto fuera del componente?
No creo que sea posible usar HeadlessUI, aunque puede crear su propio componente similar a Disclosure .
disclosures que almacene toda la información sobre las divulgaciones.map y reprodúzcalas.isClose de las divulgaciones y también maneja los atributos de aria .isOpen de la divulgación en la que se hizo clic y cierre todas las demás divulgaciones.Echa un vistazo al fragmento a continuación:
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> ); }