Search code examples
javascripthtmlreactjsdocusaurus

How to create buttons that will show / hide the state of all detail tags in a Docusaurus project?


Following from the discussion here and here, I'd like to create two buttons that will show / hide the state of all detail tags in a Docusaurus project.

Currently, the best candidate code I have for this is the following:

const React = require('react')
const {useState} = React;

const SamplePage = (props) => {
    const [isOpen, setIsOpen] = useState(false); 
    const siteConfig = props.config

    return (
        <div>
            <details open={isOpen}>
                <summary>
                    First text detail.
                </summary>
                <p>testing</p>
            </details>
            <details open={isOpen}>
                <summary>
                    Second text detail.
                </summary>
                <p>testing</p>
            </details>
            <details open={isOpen}>
                <summary>
                    Third text detail.
                </summary>
                <p>testing</p>
            </details>

            <button onClick={() => setIsOpen(true)}>Open All Details.</button>
            <button onClick={() => setIsOpen(false)}>Close All Details.</button>
        </div>
    );
  }

module.exports = SamplePage;

The Docusaurus server loads this page perfectly fine, but the buttons have no onClick effect. And this is regardless of whether I switch the button booleans from true to false.

As can be seen from the previous answers, the code snippets for this construction work just fine. However, I believe Docusaurus is doing something silly and opinionated in the background which is interfering with this simple functionality. What is the source of this issue and how can it be fixed?


Solution

  • I arrived at a different solution to this problem, which works fine for my purposes but might be a bit hacky and could certainly be improved. The idea is just to split the SamplePage into two identical modules: SamplePageA and SamplePageB, with the only difference being the useState() boolean. So, in effect, you only need 2 links to switch all detail tags from the open to the closed state. Of course, this requires pointless duplication of the modules, but this is the only solution I know to achieve the intended effect.

    const React = require('react')
    
    const {useState} = React;
    
    const SamplePageA = () => { // or SamplePageB;
        const [isOpen, setIsOpen] = useState(true); // or false
    
        return (
          <div id="test">
            <details open={isOpen}>
                <summary>
                    First text detail.
                </summary>
                <p>testing</p>
            </details>
            <details open={isOpen}>
                <summary>
                    Second text detail.
                </summary>
                <p>testing</p>
            </details>
            <details open={isOpen}>
                <summary>
                    Third text detail.
                </summary>
                <p>testing</p>
            </details>
    
            <a href="SamplePageA">Open All Details</a>
            <a href="SamplePageB">Close All Details</a>
    
          </div>
        );
      }
    
    module.exports = SamplePageA; // or SamplePageB;
    

    Feel free to edit this post if you have a better idea.