# Price Menu Widget

> Restaurant-style menu listing with item name, description, price, and optional variations / sizes. Each menu item is a Repeater row; variations are a nested Repeater inside each item.

**Class file:** `includes/Elements/Price_Menu.php` (1,374 lines)
**Slug:** `price-menu` (widget id `eael-price-menu`)
**Public docs:** <https://essential-addons.com/elementor/docs/price-menu/>
**Pro-shared:** Pro-only. Uses Pro's `Helper`.

## Overview

Menu-style price list — food menus, service menus, anything with "name — description — price". Each item supports an optional variations sub-repeater (e.g. Small / Medium / Large with separate prices). Image per item optional. No template files — pure inline rendering with CSS-driven layout variations.

## Pro vs Lite

Pro-only.

## File Map

| File | Role |
| --- | --- |
| `includes/Elements/Price_Menu.php` | Widget class (1,374 lines) |
| `src/css/view/price-menu.scss` → `assets/front-end/css/view/price-menu.min.css` | Menu styling |
| `config.php` entry `'price-menu'` | Self CSS only (no JS) |

No frontend JS — pure server-rendered.

## Architecture

- **Nested Repeater** — outer `$repeater` (line 75) for menu items; inner `$variation_repeater` (line 170) for per-item variations. Pro embeds the variation Repeater via `$repeater->add_control(...)` (line 208) — Elementor supports nested Repeaters with this pattern.
- **No JS** — visible price + dotted-line filler + tail-aligned price done in CSS via flexbox or `::after` content.
- **Composes Pro's `Helper`** (line 13 in headers).
- **No template directory** — single inline render; layout variations are CSS-driven on the same DOM structure.

## Render Output

```html
<div class="eael-price-menu">
  <!-- One block per menu item -->
  <div class="eael-price-menu-item">
    [?] <img class="eael-price-menu-image" src="{item_image}" />
    <div class="eael-price-menu-content">
      <div class="eael-price-menu-header">
        <h3 class="eael-price-menu-title">{item_name}</h3>
        <span class="eael-price-menu-dots"></span>
        <span class="eael-price-menu-price">${price}</span>
      </div>
      [?] <p class="eael-price-menu-description">{description}</p>
      [?] <span class="eael-price-menu-badge">{badge}</span>
      <!-- Variations (nested Repeater) -->
      [?] <ul class="eael-price-menu-variations">
        <li><span class="size">Small</span> <span class="dots"></span> <span class="price">$5</span></li>
        <li><span class="size">Large</span> <span class="dots"></span> <span class="price">$9</span></li>
      </ul>
    </div>
  </div>
</div>
```

## Controls Reference

| Control id | Tab → Section | Type | Purpose |
| --- | --- | --- | --- |
| Items Repeater | Content → section_price_menu | REPEATER | Menu items |
| (per-item) Item name | Inside Items Repeater | TEXT | Name |
| (per-item) Item description | Inside Items Repeater | TEXTAREA | Description |
| (per-item) Item price | Inside Items Repeater | TEXT | Price string |
| (per-item) Item image | Inside Items Repeater | MEDIA | Optional image |
| (per-item) Variations (nested Repeater) | Inside Items Repeater | REPEATER | Per-item size/price rows |
| (per-variation) Size + Price | Inside Variations Repeater | TEXT + TEXT | Variation rows |

## Conditional Dependencies

```text
Per-item: image set → image renders
Per-item: variations present → variations list renders
Per-item: badge set → badge renders
```

## JavaScript Lifecycle

N/A — pure CSS widget.

## Hooks & Filters

Standard widget render. No Pro-emitted hooks.

## Common Issues

| Symptom | Likely cause | Diagnose | Fix |
| --- | --- | --- | --- |
| Dotted-line filler missing | CSS `::after` not rendering | Inspect computed CSS on `.eael-price-menu-dots` | Verify Pro CSS not overridden by theme |
| Variations expanded in editor but collapsed on frontend | No JS controls expand state — variations are always visible | — | Expected; variations have no toggle |
| Price not right-aligned | Flexbox not applied | Inspect `.eael-price-menu-header` | Confirm flexbox layout intact |
| Image too large | No image-size constraint | Inspect `.eael-price-menu-image` | Use Pro image-size control or add explicit width style |
| Many items perf | Large Repeater + image lazy-load missing | Inspect HTML size | Add lazy loading to images (`loading="lazy"`) |

## Known Limitations

- **No expand/collapse JS** — all variations always visible. No "show details" interaction
- **No category headers built-in** — multi-section menus (Starters / Mains / Desserts) require multiple widget instances or manually-entered section headers
- **Nested Repeater UX** — Elementor's nested Repeater is functional but visually cluttered; many menu items × variations = scrolling pain in editor
- **No print stylesheet** — menus often printed; would benefit from `@media print` rules
- **Image lazy-load not enforced**

## Cross-References

- Sibling: [`multicolumn-pricing-table.md`](multicolumn-pricing-table.md), [`pricing-slider.md`](pricing-slider.md)
- Shared patterns: [`_patterns.md`](_patterns.md)
