Source: uswdsAccordionSection/uswdsAccordionSection.js

import { LightningElement, api } from "lwc";

/**
 * @class
 * @alias uswds-accordion-section
 * @hideconstructor
 * @description A section within an accordion component, managing its expanded state and content visibility.
 * @extends LightningElement
 * @author Mark Vogelgesang <movogelgesang@gmail.com>
 * @since 1.0.0
 */
export default class UswdsAccordionSection extends LightningElement {
  /**
   * @type {string}
   * @description The header text displayed for this accordion section.
   */
  @api header;

  /**
   * @type {string}
   * @description A unique identifier for this accordion section.
   */
  @api sectionId;

  /**
   * @type {boolean}
   * @default false
   * @description Determines if the section should have a top margin applied.
   */
  @api applyTopMargin = false;

  /**
   * @type {boolean}
   * @default false
   * @description Indicates whether the section is currently expanded.
   */
  @api isExpanded = false;

  /**
   * @private
   * @description Getter method to dynamically build the class string for the accordion heading.
   *              Adds a margin class if the `applyTopMargin` property is true.
   * @returns {string} - The class string for the accordion heading.
   */
  get headingClasses() {
    // Start with the base class
    let classes = "usa-accordion__heading";

    // Add the margin class only if the parent tells it to
    if (this.applyTopMargin) {
      classes += " add-margin-top";
    }

    return classes;
  }

  /**
   * @private
   * @type {boolean}
   * @description Getter method to determine if the accordion content should be hidden.
   *              Returns true if the accordion section is not expanded.
   * @returns {boolean} - True if the content should be hidden, false otherwise.
   */
  get isContentHidden() {
    return !this.isExpanded;
  }

  /**
   * @method toggle
   * @memberof UswdsAccordionSection
   * @description Public method to toggle the expanded state of the accordion section.
   *              If an argument is provided, it sets the expanded state to that value.
   *              Otherwise, it toggles the current state.
   *
   * @param {boolean} [expand] - Optional. The desired expanded state.
   * @returns {void}
   * @public
   */
  @api
  toggle(expand) {
    this.isExpanded = typeof expand === "boolean" ? expand : !this.isExpanded;
  }

  /**
   * @method
   * @private
   *
   * @description Handles the click event on the accordion header.
   *              Dispatches a custom event `sectiontoggle` with details about the section's state.
   * @returns {void}
   */
  handleHeaderClick() {
    const customEvent = new CustomEvent("sectiontoggle", {
      bubbles: true,
      composed: true,
      detail: {
        id: this.sectionId,
        isExpanded: this.isExpanded
      }
    });
    this.dispatchEvent(customEvent);
  }
}