# Smart Post List Widget

> Vertical post list with featured + sidebar layout (advanced preset) and 3 additional presets. Optional AJAX-driven post search box inside the widget. Pagination (numbered / nav arrows / scroll).

**Class file:** `includes/Elements/Post_List.php` (3,276 lines)
**Slug:** `post-list` (widget id `eael-post-list`, public name "Smart Post List")
**Public docs:** <https://essential-addons.com/elementor/docs/smart-post-list/>
**Pro-shared:** Pro-only. Composes Lite's `Template_Query` trait.

## Overview

Renders a post list with 4 layout presets (default, advanced, preset-2, preset-3). The "advanced" preset includes a featured/highlighted post + sidebar list plus an optional AJAX-search input box (Pro-owned `ajax-post-search.min.js`). Supports numbered pagination and navigation-arrow pagination with scroll-to-target. Composes Lite's `Template_Query` trait for query building.

## Pro vs Lite

Pro-only. Reuses Lite's `Template_Query` trait (via `use \Essential_Addons_Elementor\Traits\Template_Query;`).

## File Map

| File | Role |
| --- | --- |
| `includes/Elements/Post_List.php` | Widget class (3,276 lines) — controls + render + pagination renderers |
| `includes/Template/Post-List/default.php` | Default preset template |
| `includes/Template/Post-List/advanced.php` | Advanced (featured + sidebar) template |
| `includes/Template/Post-List/preset-2.php` | Preset 2 template |
| `includes/Template/Post-List/preset-3.php` | Preset 3 template |
| `src/css/view/post-list.scss` → `assets/front-end/css/view/post-list.min.css` | List + layout styling |
| `src/js/view/post-list.js` → `assets/front-end/js/view/post-list.min.js` | Pagination + scroll behaviour |
| `src/js/view/ajax-post-search.js` → `assets/front-end/js/view/ajax-post-search.min.js` | AJAX search input handler |
| `config.php` entry `'post-list'` | Self CSS + 2 self JS |

## Architecture

- **4 templates via preset switch** — `render()` (line 2858) dispatches to one of 4 template files based on `eael_post_list_layout_type`. Same template-include pattern as Post_Block but with 4 variants.
- **`Template_Query` trait from Lite** — line 25: `use \Essential_Addons_Elementor\Traits\Template_Query;`. Provides `template_query_args` and related helpers. When Lite refactors this trait, Post_List breaks. See [`_patterns.md § Helper imports`](_patterns.md#helper-imports).
- **AJAX post search** — separate `ajax-post-search.min.js` enqueued unconditionally. Renders inside `advanced` layout only (line 2993 condition). Search form HTML built inline in `render()`. AJAX handler lives in Lite.
- **Pagination renderers split into 2 methods** — `render_navigation_pagination` (line 3153, arrow-style) and `render_page_number_pagination` (line 3196, numbered). Dispatched by `pagination_type` setting.
- **`render_featured_post_meta_dates`** (line 2798) — helper for the featured post block's meta. Distinct from per-card meta.
- **Two protected arrays as state** — `$all_terms`, `$tax_query` — populated during render for use across template includes.

## Render Output (advanced preset)

```html
<div class="eael-post-list-container layout-advanced eael-post-list-{element-id}">
  [?] <div class="eael-post-list-header">
    <div class="post-list-ajax-search-form">
      <form>
        <input type="text" placeholder="Search posts..." />
        <i class="fa-search"></i>
      </form>
    </div>
  </div>
  <div class="eael-post-list-featured">
    <article><img /><h2>Featured Title</h2><p>Excerpt</p></article>
  </div>
  <div class="eael-post-list-sidebar">
    <ul>
      <li class="eael-post-list-item">
        <img /><div><h3>Title</h3><meta>{date}</meta></div>
      </li>
      ...
    </ul>
  </div>
  [?] <div class="eael-post-list-pagination">{numbered or arrows}</div>
</div>
```

## Controls Reference

| Control id | Tab → Section | Type | Purpose |
| --- | --- | --- | --- |
| `eael_post_list_layout_type` | Content → Layout | SELECT | `default` / `advanced` / `preset-2` / `preset-3` |
| `eael_enable_ajax_post_search` | Content → Layout | SWITCHER | Show AJAX search input (advanced layout only) |
| Query controls (post_type, term, etc.) | Content → Query | various | Lite query controls |
| `posts_per_page` | Content → Query | NUMBER | Per-page count |
| Pagination type | Content → Pagination | SELECT | `none` / `numbered` / `navigation` |
| `scroll_on_pagination` | Content → Pagination | SWITCHER | Auto-scroll to top of widget on page change |
| `scroll_offset` | Content → Pagination | NUMBER | px offset for sticky-header compensation |
| Featured post meta toggles (date / author / category) | Content → Featured Meta | SWITCHER | Per-element visibility |
| Read-more button | Content → Content | SWITCHER + TEXT | Toggle + label |

## Conditional Dependencies

```text
eael_post_list_layout_type = 'advanced'
  └── shows eael_enable_ajax_post_search

eael_enable_ajax_post_search = 'yes'
  └── shows search input styling controls

pagination_type = 'numbered'
  └── shows page-number style controls

pagination_type = 'navigation'
  └── shows prev/next arrow controls

pagination_type != 'none'
  └── shows scroll_on_pagination + scroll_offset
```

## JavaScript Lifecycle

`src/js/view/post-list.js` — pagination + scroll handler. `src/js/view/ajax-post-search.js` — AJAX search box (debounced input → AJAX → re-render result list).

Both enqueued unconditionally for any post-list widget instance (even when advanced layout isn't selected). Minor inefficiency.

## Hooks & Filters

Standard widget render. AJAX search and pagination go through Lite's AJAX handlers.

## Common Issues

| Symptom | Likely cause | Diagnose | Fix |
| --- | --- | --- | --- |
| AJAX search input missing | Layout not "advanced" | Verify `eael_post_list_layout_type` | Switch to advanced layout |
| Search returns no results | Lite AJAX endpoint not registered or term mismatch | Network: inspect AJAX response | Verify Lite is active; check term param against query args |
| Pagination doesn't scroll | `scroll_on_pagination` off or `scroll_offset` 0 | Check settings | Toggle on; set offset to header height |
| Featured post missing | `posts_per_page` < 2 | Featured + sidebar needs ≥ 2 posts | Increase `posts_per_page` |
| Layout breaks at narrow widths | CSS grid not responsive | Inspect `.eael-post-list-container.layout-advanced` media queries | Verify SCSS source has mobile breakpoints |

## Known Limitations

- **AJAX search JS loaded for every post-list instance** — even when advanced layout isn't used. Move to conditional config.php entry.
- **`Template_Query` trait is Lite-coupled** — Lite refactors break Post_List. See `/pro-lite-sync`.
- **4 templates × custom CSS per layout = large `register_controls`** — 3,276 lines for this widget, mostly per-layout styling
- **No template-loader hook** — adding a 5th preset requires `render()` switch edit
- **Search input HTML inline in `render()`** — should move to a partial template
- **Featured post meta is its own render path** — `render_featured_post_meta_dates` separate from per-card meta; risk of drift

## Cross-References

- Architecture: [`docs/architecture/pro-lite-bridge.md`](../architecture/pro-lite-bridge.md) — `Template_Query` trait composition
- Shared patterns: [`_patterns.md`](_patterns.md)
- Skill: [`/pro-lite-sync`](../../.claude/skills/pro-lite-sync/SKILL.md)
