# Team Member Carousel Widget

> Swiper carousel of team-member cards — photo, name, role, bio, social links. Multiple per-card presets driven by extensive style controls.

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

## Overview

Card-based carousel for team / staff / speakers. Each card has photo, name, position, bio excerpt, social-link list (FA5 icons + URLs). Pro adds carousel mechanics to what Lite has as the static Team Member widget. 2,857 lines mostly per-card style controls (image / name / role / bio / social-icon per-platform).

## Pro vs Lite

Pro-only widget. Lite has a static Team Member widget (single card); this Pro widget is multi-card with carousel.

## File Map

| File | Role |
| --- | --- |
| `includes/Elements/Team_Member_Carousel.php` | Widget class (2,857 lines) |
| `src/css/view/team-member-carousel.scss` → `assets/front-end/css/view/team-member-carousel.min.css` | Styling |
| `src/js/view/team-member-carousel.js` → `assets/front-end/js/view/team-member-carousel.min.js` | Swiper init |
| `config.php` entry `'team-member-carousel'` | Self CSS + self JS |

`get_style_depends()` returns `['e-swiper']` (line 112–117).

## Architecture

- **`get_style_depends() => ['e-swiper']`** — Elementor Swiper handle.
- **Composes Lite's `Helper`** (line 17).
- **No template directory** — single inline render. Layout variations are CSS-driven on the same DOM.
- **`swiper-container-wrap` arrow buttons** — same standard pattern as sibling carousels.
- **Repeater of team members** — each row: image / name / position / description / social-links Repeater (nested).
- **Per-card style controls** — image / name / position / bio / per-social-platform styling. Major contributor to 2,857-line size.

## Render Output

```html
<div class="swiper-container-wrap eael-team-member-carousel-{element-id}">
  <div class="eael-team-member-carousel swiper">
    <div class="swiper-wrapper">
      <div class="swiper-slide">
        <div class="eael-team-member-card">
          [?] <img class="eael-team-image" src="{photo}" />
          <div class="eael-team-content">
            <h3 class="eael-team-name">{name}</h3>
            [?] <span class="eael-team-position">{position}</span>
            [?] <p class="eael-team-bio">{bio}</p>
            [?] <ul class="eael-team-social">
              <li><a href="{url}" target="_blank"><i class="{icon-class}"></i></a></li>
              ...
            </ul>
          </div>
        </div>
      </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 |
| --- | --- | --- | --- |
| Team members Repeater | Content → Members | REPEATER | One row per member |
| (Per-member) image | Inside Repeater | MEDIA | Photo |
| (Per-member) name / position / bio | Inside Repeater | TEXT / TEXT / TEXTAREA | Identity + bio |
| (Per-member) social-links Repeater | Inside Repeater | REPEATER (nested) | Per-platform URL + icon |
| Per-breakpoint items | Content → Carousel | SLIDER | `items_desktop` / `_tablet` / `_mobile` |
| Carousel autoplay / arrows / dots / effect | Content → Carousel | various | Swiper config |
| Show toggles (image / position / bio / social) | Content → Display | SWITCHER | Per-element visibility |
| Per-region styling | Style → ... | various | Image / name / position / bio / social styling |

## Conditional Dependencies

```text
show_image / show_position / show_bio / show_social → per-element visibility + style controls
arrows = 'yes' → arrow icon pickers
dots = 'yes' → pagination style
autoplay = 'yes' → autoplay_speed + pause_on_hover
```

## JavaScript Lifecycle

Standard Swiper init pattern via `elementorFrontend.utils.swiper` async loader.

## Hooks & Filters

Standard widget render. No Pro-emitted hooks.

## Common Issues

| Symptom | Likely cause | Diagnose | Fix |
| --- | --- | --- | --- |
| Card heights uneven | No equal-height JS or CSS | Inspect `.eael-team-member-card` heights | Use CSS `display: flex` on swiper-slide to equalize |
| Social icons missing | FA4 / FA5 mismatch | Inspect icon class | Use FA5 ICONS picker; legacy text may use FA4 strings |
| Long bios truncate weirdly | No max-line clamp | Inspect computed CSS | Add `-webkit-line-clamp` or shorten bios |
| Carousel loops weirdly with 2 members | Swiper loop + few slides | — | Disable loop OR add more members |
| Per-card variations want skin | Single template only | — | Use Advanced_Menu-style skins (not implemented here); refactor candidate |

## Known Limitations

- **2,857 lines** — heavy per-card styling controls; refactor candidate
- **Single template** — no preset / skin system; all visual variations come from CSS controls
- **Nested Repeater** (members × social links) — editor UX heavy
- **No `prefers-reduced-motion`** for autoplay
- **FA4 / FA5 mix** for social icons depending on user's Pro version history
- **Per-card height equalization not enforced** — Swiper allows uneven heights; CSS responsibility

## Cross-References

- Lite sibling: `Team_Member` (static single-card widget)
- Sibling carousels: [`flip-carousel.md`](flip-carousel.md), [`logo-carousel.md`](logo-carousel.md), [`testimonial-slider.md`](testimonial-slider.md), [`post-carousel.md`](post-carousel.md)
- Shared patterns: [`_patterns.md`](_patterns.md)
