# Pricing Slider Widget

> Interactive pricing comparison where users drag a slider to see different tiers update live. Each tier is a configured "panel" with price, feature list, badge, status, and CTA.

**Class file:** `includes/Elements/Pricing_Slider.php` (2,966 lines)
**Slug:** `pricing-slider` (widget id `eael-pricing-slider`)
**Public docs:** <https://essential-addons.com/elementor/docs/pricing-slider/>
**Pro-shared:** Pro-only. Uses Pro's `Helper`.

## Overview

Drag-slider that switches between pricing tiers (Basic / Pro / Enterprise / etc.). Each tier has title, subtitle, badge icon, status pill, price, feature list, button. As the user moves the slider, the displayed tier updates with smooth transition. Multiple feature-list columns supported per tier (`eael_pricing_panel_feature_list_number`). Uses Pro's `Helper` (not Lite's) — Pro-specific implementation.

## Pro vs Lite

Pro-only.

## File Map

| File | Role |
| --- | --- |
| `includes/Elements/Pricing_Slider.php` | Widget class (2,966 lines) |
| `src/css/view/pricing-slider.scss` → `assets/front-end/css/view/pricing-slider.min.css` | Slider track + panels styling |
| `src/js/view/pricing-slider.js` → `assets/front-end/js/view/pricing-slider.min.js` | Slider drag + tier transition |
| `config.php` entry `'pricing-slider'` | Self CSS + self JS |

## Architecture

- **Repeater-based tiers** — each tier is a Repeater row. `eael_pricing_panel_control_id` (line 321) is a user-set identifier for cross-tier references (e.g. "this feature shown only in tiers Pro and Enterprise"). Control aliasing with admin-side `_alert` notice control (line 330).
- **Multi-column feature list per tier** — `eael_pricing_panel_feature_list_number` controls how many sub-columns of features each tier displays. Used in `range()` conditions throughout (e.g. line 515: `'eael_pricing_panel_feature_list_number[size]!' => range( 0, $i - 1 )`).
- **Conditional show by feature-count** — Pro uses Elementor's `condition` with `range()`-generated lists to hide controls that depend on feature columns existing. Complex condition logic spread across hundreds of lines.
- **Badge icon + status pill** as separate optional decorators per tier — badges (line 373, 386), status (line 414, 423, 435).
- **No template directory** — single inline render, slider behaviour switches active-tier class on parent wrapper, all tiers render in DOM, only one visible at a time via CSS.

## Render Output

```html
<div class="eael-pricing-slider-wrapper">
  <!-- Slider track -->
  <div class="eael-pricing-slider-control">
    <input type="range" min="0" max="{tier_count - 1}" value="0" />
    <ul class="eael-pricing-slider-labels">
      <li class="active">{tier-1 title}</li>
      <li>{tier-2 title}</li>
      ...
    </ul>
  </div>
  <!-- All tier panels render; one visible via CSS -->
  <div class="eael-pricing-slider-panels">
    <div class="eael-pricing-panel active" data-tier="{control_id}">
      [?] <div class="eael-pricing-panel-badge"><i class="{badge_icon}"></i></div>
      [?] <span class="status">{status_title}</span>
      <h3>{title}</h3>
      [?] <span class="subtitle">{subtitle}</span>
      <div class="eael-pricing-panel-price">
        <span class="currency">$</span><span class="amount">29</span><span class="period">/mo</span>
      </div>
      <!-- Per-tier feature columns -->
      <div class="eael-pricing-panel-features">
        <ul class="column-1">
          <li>{feature 1}</li>
          ...
        </ul>
        [?] <ul class="column-2">...</ul>
      </div>
      <a class="eael-pricing-panel-button">Buy Now</a>
    </div>
    <div class="eael-pricing-panel" data-tier="...">...</div>
    ...
  </div>
</div>
```

## Controls Reference (per tier)

| Control id | Type | Purpose |
| --- | --- | --- |
| `eael_pricing_panel_control_id` | TEXT | Tier identifier |
| `eael_pricing_panel_title` | TEXT | Tier name |
| `eael_pricing_panel_show_subtitle` + `_subtitle` | SWITCHER + TEXT | Subtitle |
| `eael_pricing_panel_show_badge_icon` + `_badge_icon` | SWITCHER + ICONS | Badge icon |
| `eael_pricing_panel_status` + `_show` + `_title` | various | Status pill |
| `eael_pricing_panel_feature_list_number` | SLIDER | Number of feature sub-columns |
| Price (currency, amount, period) | various | Pricing display |
| Button (label, link, style) | various | CTA |
| (Many more — 2,966 lines total) | — | — |

## Conditional Dependencies

Heavily condition-driven. Feature-column controls use `range()` to gate visibility based on the tier's feature-list-number setting. Each feature-list column has its own block of conditions referencing `eael_pricing_panel_feature_list_number[size]`.

## JavaScript Lifecycle

`src/js/view/pricing-slider.js` — listens to `<input type="range">` change events, swaps `.active` class on the matching `.eael-pricing-panel`. Smooth CSS transitions handle the visual fade. Possibly debounced for smooth drag.

## Hooks & Filters

Standard widget render. No Pro-emitted hooks.

## Common Issues

| Symptom | Likely cause | Diagnose | Fix |
| --- | --- | --- | --- |
| Slider doesn't move | `<input type="range">` styling broken | DevTools: inspect range input | Verify Pro's slider CSS not overridden by theme |
| Wrong tier shows on drag | `data-tier` mismatch with slider value | Inspect tier ordering | Re-order Repeater rows |
| Feature columns mis-align | Different tiers have different feature-column counts | Inspect each tier's `feature_list_number` | Match column counts across tiers |
| Badge / status overlap title | CSS positioning | Inspect computed CSS | Use Pro's spacing controls |
| Mobile slider too narrow | Range input default width | Inspect responsive width | Add responsive override |

## Known Limitations

- **2,966 lines** — heaviest of the pricing widgets. Per-tier control replication. Refactor candidate.
- **Range input styling is browser-specific** — older browsers may render the slider differently
- **No keyboard accessibility validation** — `<input type="range">` has built-in keyboard support but tier-label sync may be missing
- **All tiers render in DOM** — large feature lists = bulky HTML; only one visible at a time
- **No `prefers-reduced-motion`** — transitions run regardless
- **`range()`-based conditions** — opaque to readers; refactor into named methods

## Cross-References

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