Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

650
Vistas
How to collapse Siblings with Headless UI

To make the accordion component with Headless UI, I have used Disclosure component. But I have a problem to control the collapse/expand state for it's siblings.

So, I want to close other siblings when I open one, but Disclosure component is only supporting internal render props, open and close. So, I can't control it outside of the component and can't close others when I open one.

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>
  )
}

How do we control the close/open state outside of the component?

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

I don't think so it's possible using HeadlessUI, although you can create your own Disclosure like component.

  • Lift the state up to the parent component by creating a disclosures state that stores all the information about the disclosures.
  • Loop over the disclosures using map and render them.
  • Render a button that toggles the isClose property of the disclosures and also handles the aria attributes.
  • On button click, toggle the isOpen value of the clicked disclosure and close all the other disclosures.

Checkout the snippet below:

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>
  );
}
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda