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

Code before:
 * @example
 * <section data-controller="w-reveal">
 *  <button type="button" data-action="w-reveal#toggle" data-w-reveal-target="toggle" aria-controls="my-content" type="button">Toggle</button>
 *  <div id="my-content">CONTENT</div>
 * </section>
 */
export class RevealController extends Controller<HTMLElement> {
  static classes = [
    'closed',
    'closeIcon',
    'opened',
    'openedContent',
    'openIcon',
  ];

  static targets = ['content', 'toggle'];

  static values = {
    closed: { default: false, type: Boolean },
    peeking: { default: false, type: Boolean },
    peekTarget: { default: '', type: String },
    store: { default: '', type: String },
  };

  declare closedValue: boolean;
  declare peekingValue: boolean;

  declare readonly closedClass: string;
  declare readonly closedClasses: string[];
  declare readonly closeIconClass: string;
  declare readonly contentTarget: HTMLElement;
  declare readonly contentTargets: HTMLElement[];
  declare readonly hasClosedClass: boolean;
  declare readonly hasCloseIconClass: string;
  declare readonly hasContentTarget: boolean;
  declare readonly hasOpenIconClass: string;
  declare readonly hasToggleTarget: boolean;
  declare readonly initialClasses: string[];
  declare readonly openedClasses: string[];
  declare readonly openedContentClasses: string[];
  declare readonly openIconClass: string;
  declare readonly peekTargetValue: string;
  declare readonly storeValue: string;
  declare readonly toggleTarget: HTMLButtonElement;
  declare readonly toggleTargets: HTMLButtonElement[];

  cleanUpPeekListener?: () => void;

  connect() {
    // If peeking is being used, set up listener and its removal on disconnect


Review comment (suggestion):
Let's call this `storageKey`, and instead use it as a key and not a value. After a bit of digging, I can see that this gets a bit confusing and we can add more flexibility if we make this the key.

```suggestion
    storageKey: { default: '', type: String },
```

Code after:
/**
 * Adds the ability to make the controlled element be used as an
 * opening/closing (aka collapsing) element.
 * Supports, and relies on, correct usage of aria-* attributes.
 *
 * @see https://w3c.github.io/aria/#aria-expanded
 *
 * @example - Basic usage
 * ```html
 * <section data-controller="w-reveal">
 *   <button type="button" data-action="w-reveal#toggle" data-w-reveal-target="toggle" aria-controls="my-content" type="button">Toggle</button>
 *   <div id="my-content">CONTENT</div>
 * </section>
 * ```
 *
 * @example - Saving to local storage
 * ```html
 * <section data-controller="w-reveal" data-w-reveal-storage-key="saved-state">
 *   <button type="button" aria-controls="my-content" type="button" data-action="w-reveal#toggle" data-w-reveal-target="toggle">Toggle</button>
 *   <div id="my-content">CONTENT</div>
 * </section>
 * ```
 */
export class RevealController extends Controller<HTMLElement> {
  static classes = [
    'closed',
    'closeIcon',
    'opened',
    'openedContent',
    'openIcon',
  ];

  static targets = ['content', 'toggle'];

  static values = {
    closed: { default: false, type: Boolean },
    peeking: { default: false, type: Boolean },
    peekTarget: { default: '', type: String },
    storageKey: { default: '', type: String },
  };

  declare closedValue: boolean;
  declare peekingValue: boolean;

  declare readonly closedClasses: string[];
  declare readonly closeIconClass: string;
  declare readonly hasCloseIconClass: string;
  declare readonly hasOpenIconClass: string;
  declare readonly openedClasses: string[];
  declare readonly openedContentClasses: string[];
  declare readonly openIconClass: string;