# Logo Carousel Widget

> Swiper-based logo grid/carousel with optional Tooltipster tooltips on hover and SVG icon embed support.

**Class file:** `includes/Elements/Logo_Carousel.php` (1,599 lines)
**Slug:** `logo-carousel` (widget id `eael-logo-carousel`)
**Public docs:** <https://essential-addons.com/elementor/docs/logo-carousel/>
**Pro-shared:** Pro-only. Uses Lite's `Classes\Helper` + Lite's Tooltipster vendor + Elementor's `e-swiper` handle.

## Overview

Brand logo carousel — each Repeater row is a logo (image or SVG) with optional tooltip, link, and per-slide hover opacity. Uses **Swiper via `e-swiper` style handle** (no Pro Swiper rebundle) for carousel mechanics, **Tooltipster from Lite** for hover tooltips. SVG icon embed via dedicated wrapper class (`eael-logo-carousel-svg-icon`).

## Pro vs Lite

Pro-only widget. Reuses Lite's Tooltipster vendor lib (CSS + JS) via `EAEL_PLUGIN_PATH` references in `config.php`.

## File Map

| File | Role |
| --- | --- |
| `includes/Elements/Logo_Carousel.php` | Widget class (1,599 lines) |
| `src/css/view/logo-carousel.scss` → `assets/front-end/css/view/logo-carousel.min.css` | Pro styling |
| `src/js/view/logo-carousel.js` → `assets/front-end/js/view/logo-carousel.min.js` | Swiper + Tooltipster init |
| `EAEL_PLUGIN_PATH/assets/front-end/css/lib-view/tooltipster/tooltipster.bundle.min.css` | Lite — Tooltipster CSS |
| `EAEL_PLUGIN_PATH/assets/front-end/js/lib-view/tooltipster/tooltipster.bundle.min.js` | Lite — Tooltipster JS |
| `config.php` entry `'logo-carousel'` | Lite Tooltipster + Pro CSS + Pro JS |

`get_style_depends()` returns `['e-swiper']` (line 108–109).

## Architecture

- **`get_style_depends() => ['e-swiper']`** — opts into Elementor's Swiper CSS handle. See [`.claude/rules/widget-development.md`](../../.claude/rules/widget-development.md) "Elementor-Provided Libraries".
- **Tooltipster from Lite** — Pro doesn't ship its own Tooltipster; reuses Lite's copy via `EAEL_PLUGIN_PATH`. Failure mode: if Lite is deactivated mid-test, the file resolution breaks.
- **SVG icon embed** — `.eael-logo-carousel-svg-icon` (line 944) is a dedicated wrapper class for inline SVG logos. Lets users use scalable SVG instead of raster.
- **Per-slide hover opacity** — line 813: `.swiper-slide:hover img` selector. CSS-driven hover state.
- **Standard `swiper-container-wrap` arrow buttons** — same selector pattern as sibling carousels.

## Render Output

```html
<div class="swiper-container-wrap eael-logo-carousel-{element-id}">
  <div class="eael-logo-carousel swiper">
    <div class="swiper-wrapper">
      <div class="swiper-slide">
        [?] <a href="{link}" {target}>
          [?] <img src="{logo}" alt="{title}" data-tooltipster="{tooltip-text}" />
          [?] <span class="eael-logo-carousel-svg-icon">{inline SVG}</span>
        [?] </a>
      </div>
      ...
    </div>
    [?] <div class="swiper-button-next"></div>
    [?] <div class="swiper-button-prev"></div>
    [?] <div class="swiper-pagination"></div>
  </div>
</div>
```

## Controls Reference

| Control id | Tab → Section | Type | Purpose |
| --- | --- | --- | --- |
| Items Repeater | Content → Logos | REPEATER | Per-logo image/SVG, link, tooltip |
| Image / SVG toggle | Inside Repeater | CHOOSE | `image` or `svg` |
| Tooltip text | Inside Repeater | TEXT | Tooltipster content |
| Tooltip position | Content → Tooltip | SELECT | `top` / `bottom` / `left` / `right` |
| Per-breakpoint items count | Content → Carousel | SLIDER | `items_desktop` / `_tablet` / `_mobile` |
| Carousel autoplay / arrows / dots / effect / speed | Content → Carousel | various | Swiper config |
| Hover opacity | Style → Logos | SLIDER | `:hover img { opacity }` |

## Conditional Dependencies

```text
Per-logo source = 'svg' → SVG textarea visible, image picker hidden
Per-logo source = 'image' → image picker visible, SVG hidden
tooltip toggle = 'yes' → Tooltipster position controls visible
arrows = 'yes' → arrow icon pickers
```

## JavaScript Lifecycle

`src/js/view/logo-carousel.js`:

- Swiper init via `elementorFrontend.utils.swiper` (lazy)
- Tooltipster init on `[data-tooltipster]` elements: `$logos.tooltipster({ ... })`

## Hooks & Filters

Standard widget render. No Pro-emitted hooks.

## Common Issues

| Symptom | Likely cause | Diagnose | Fix |
| --- | --- | --- | --- |
| Tooltips don't show | Tooltipster not loaded (Lite deactivated?) | DevTools: check `$.fn.tooltipster` | Activate Lite |
| SVG not rendering | SVG content escaped | Inspect `.eael-logo-carousel-svg-icon` HTML | Verify SVG textarea allows raw markup via `wp_kses` |
| Logos different sizes | No fixed-height constraint | Inspect computed sizes | Add CSS height constraint or use image-size control |
| Hover opacity not animating | No CSS transition | Inspect `:hover` rule | Add `transition: opacity 0.3s` to base rule |
| Mobile shows all logos at once | Per-breakpoint `items_mobile` not set | Check responsive controls | Set `items_mobile` |

## Known Limitations

- **Tooltipster from Lite** — coupling makes Pro non-functional (tooltips broken) if Lite removed
- **SVG security** — user-pasted SVG sanitization depends on `wp_kses` allowlist; verify XSS-safe in render
- **No lazy-load for logos** — every logo loads on page render
- **Tooltipster is jQuery-based** — same architectural debt as Flip_Carousel's Flipster
- **No grid mode** — strictly carousel; for static grid layout, use Logo_Gallery (verify exists in Lite or elsewhere)

## Cross-References

- Sibling: [`flip-carousel.md`](flip-carousel.md), [`team-member-carousel.md`](team-member-carousel.md), [`testimonial-slider.md`](testimonial-slider.md)
- Shared patterns: [`_patterns.md`](_patterns.md)
