Repository: wagtail/wagtail
File: client/src/controllers/RevealController.ts (TypeScript)

Code before:
  /**
   * Collects all toggles, those controlled by this controller and any external
   * that have an aria-controls references to any content target elements.
   */
  get toggles() {
    const toggles = this.contentTargets
      .map((content) => content.id)
      .flatMap((id) =>
        Array.from(
          document.querySelectorAll<HTMLButtonElement>(
            `[aria-controls~="${id}"]`,
          ),
        ),
      )
      .concat(...this.toggleTargets);
    return Array.from(new Set(toggles));
  }

  /**
   * Set the inner icon on any toggles (in scope or out of scope).
   */
  updateToggleIcon(isOpenIcon = false) {
    if (!this.hasCloseIconClass || !this.hasOpenIconClass) return;
    const closeIconClass = this.closeIconClass;
    const openIconClass = this.openIconClass;
    if (closeIconClass === openIconClass) return;

    this.toggles
      .map((toggle) => {
        const iconElement = toggle.querySelector<HTMLSpanElement>('.icon');
        const useElement = iconElement?.querySelector<SVGUseElement>('use');
        if (!useElement || !iconElement) return [];
        return [iconElement, useElement] as const;
      })
      .filter(({ length }) => length)
      .forEach(([iconElement, useElement]) => {
        if (isOpenIcon) {
          iconElement.classList.remove(closeIconClass);
          iconElement.classList.add(openIconClass);
          useElement.setAttribute('href', `#${openIconClass}`);
        } else {
          iconElement.classList.remove(openIconClass);
          iconElement.classList.add(closeIconClass);
          useElement.setAttribute('href', `#${closeIconClass}`);
        }
      });
  }

  get localStorageKey() {
    return `wagtail:${this.identifier}:opened`;
  }

Review comment (suggestion):
This comment is not at the right line, but we should move our 'storing' into the `toggle` method.

This is because this is the only method that gets called when the user actually clicks something (either to 'keep/fix' it open or to close it). We have a bit of logic to ensure we respect if the mode is peeking and then store the value accordingly.

Also, some JSDoc improvements to make this easier to follow later.

This can be a bit confusing, but remember we have a peeking and a 'click' action that is meant to toggle the mode into a fixed open/close mode.


```ts

  /**
   * Toggle the open/closed state of the controller, accounting
   * for the peeking state (visually open, but not 'fixed' as open).
   * The updated closed value will be stored in local storage if available.
   */
  toggle() {
    const newClosedValue = !this.closedValue;

    this.stored = this.peekingValue ? false : newClosedValue;

    if (this.peekingValue) {
      this.peekingValue = false;
      // if peeking and toggle clicked, is already open
      // visually set the icon to the opened variant so it can be closed.
      this.updateToggleIcon(false);

      return;
    }

    this.closedValue = newClosedValue;
  }
```

Code after:
    // If we have known toggles, dispatch on those buttons
    toggles.forEach((target) => {
      this.dispatch('toggled', {
        cancelable: false,
        detail: {
          closed: shouldClose,
        },
        target,
      });
    });
  }

  /**
   * Close (hide) the reveal content.
   */
  close() {
    this.closedValue = true;
  }

  /**
   * Open (show) the reveal content.
   */
  open() {
    this.closedValue = false;
  }

  peek() {
    if (this.closedValue) {
      this.peekingValue = true;
      this.open();
    }
  }

  /**
   * Toggle the open/closed state of the controller, accounting for the peeking state (visually open, but not 'fixed' as open).
   * The updated closed value will be stored in local storage if available.
   */
  toggle() {
    this.stored = this.peekingValue ? false : !this.closedValue;

    if (this.peekingValue) {
      this.peekingValue = false;
      // if peeking and toggle clicked, is already open
      // visually set the icon to the opened variant so it can be closed.
      this.updateToggleIcon(false);
      return;
    }
    this.closedValue = !this.closedValue;
  }

  /**