# Dropdown API

### JavaScript API

#### Global Helper: `window.Dropdowns`

* `window.Dropdowns.getAll()`: Returns an array of all initialized Dropdown instances.
* `window.Dropdowns.findById(idOrDomId)`: Finds a specific instance by its numeric ID or DOM ID (e.g., `dropdown-1`).

#### Instance Methods

If you have a reference to a dropdown instance, you can call these methods:

* `instance.open({ cascade: true })`: Opens the dropdown.
* `instance.close({ cascade: true })`: Closes the dropdown.
* `instance.toggle({ cascade: true })`: Toggles the open state.

### Custom Events

Events are dispatched from the main `[data-menu-element="dropdown"]` element and bubble up.

| Event                       | Description                                                                            |
| --------------------------- | -------------------------------------------------------------------------------------- |
| `menuDropdown:open`         | Fired when the dropdown opens.                                                         |
| `menuDropdown:close`        | Fired when the dropdown closes.                                                        |
| `menuDropdown:modeChange`   | Fired when the component switches between `dropdown`, `accordion`, or `stacked` modes. |
| `menuDropdown:open:[mode]`  | Specific open event (e.g., `menuDropdown:open:dropdown`).                              |
| `menuDropdown:close:[mode]` | Specific close event (e.g., `menuDropdown:close:stacked`).                             |

**Event Detail (`event.detail`):**

* `instanceId`: The unique numeric ID of the dropdown.
* `mode`: The current mode (`dropdown`, `accordion`, or `stacked`).
* `level`: The nesting level (0 for top-level).

***

### Examples

#### Programmatic Control

```javascript
// Find a dropdown by its DOM ID (e.g., "dropdown-1")
const dropdown = window.Dropdowns.findById("dropdown-1");

// Open a dropdown
dropdown.open();

// Close a dropdown (cascade: true closes children too)
dropdown.close({ cascade: true });

// Toggle open/closed state
dropdown.toggle();

// Close all open dropdowns on the page
window.Dropdowns.getAll()
  .filter(d => d.isOpen)
  .forEach(d => d.close({ cascade: true }));

// Find a dropdown by numeric ID
const firstDropdown = window.Dropdowns.findById(1);
```

#### Listening for Events

```javascript
// Listen for any dropdown opening
document.addEventListener("menuDropdown:open", (e) => {
  console.log(`Dropdown ${e.detail.instanceId} opened`);
  console.log(`Current mode: ${e.detail.mode}`);
  console.log(`Nesting level: ${e.detail.level}`);
});

// Listen for any dropdown closing
document.addEventListener("menuDropdown:close", (e) => {
  console.log(`Dropdown ${e.detail.instanceId} closed`);
});

// Listen for mode-specific events
document.addEventListener("menuDropdown:open:stacked", (e) => {
  console.log("A dropdown opened in stacked (mobile) mode");
});

document.addEventListener("menuDropdown:close:accordion", (e) => {
  console.log("A dropdown closed in accordion mode");
});
```

#### Detecting Mode Changes

```javascript
// Listen for responsive mode switches
document.addEventListener("menuDropdown:modeChange", (e) => {
  const { instanceId, mode, oldMode, newMode } = e.detail;
  
  console.log(`Dropdown ${instanceId} switched from ${oldMode} to ${newMode}`);
  
  // Perform actions based on new mode
  if (newMode === "stacked") {
    // Mobile stacked mode activated
    document.body.classList.add("mobile-nav-active");
  } else if (newMode === "dropdown") {
    // Desktop dropdown mode activated
    document.body.classList.remove("mobile-nav-active");
  }
});
```

#### Working with Nested Dropdowns

```javascript
// Get all dropdown instances
const allDropdowns = window.Dropdowns.getAll();

// Find top-level dropdowns only (level 0)
const topLevelDropdowns = allDropdowns.filter(d => d.level === 0);

// Find nested dropdowns (level > 0)
const nestedDropdowns = allDropdowns.filter(d => d.level > 0);

// Check if a dropdown has open children
const dropdown = window.Dropdowns.findById(1);
if (dropdown.hasOpenDescendant()) {
  console.log("This dropdown has open nested menus");
}

// Access parent/child relationships
const childDropdown = window.Dropdowns.findById(2);
if (childDropdown.parentInstance) {
  console.log("Parent dropdown ID:", childDropdown.parentInstance.id);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.nickarce.com/javascript-api/dropdown-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
