Component Contract

Testimonials

Display member quotes and testimonials to build trust and social proof for CAAT Pension Plan.

Live Demo

Two independent axes: a layout (single · grid · carousel) and an avatar type (photo · initials · icon), with an optional star rating above any quote. Each card is a <figure>/<figcaption> composing the Avatar component.

Layout — Single · photo · with rating

"After 32 years of teaching, I retired knowing my CAAT pension would be there for me. The defined benefit plan gives me peace of mind — I never have to worry about outliving my savings."

Margaret Chen
Margaret Chen
Retired Educator · Durham College

Layout — Grid · photo

"Retiring at 60 felt like a dream, but CAAT made it a reality. My pension income replaced 70% of my working salary from day one."

Robert Tremblay
Robert Tremblay
Retired Facilities Manager · Conestoga College

"The inflation protection built into my CAAT pension means my purchasing power stays strong year after year. That's something no RRSP can guarantee."

Linda Kaur
Linda Kaur
Retired Librarian · Sheridan College

"We partnered with CAAT five years ago. Since then, employee satisfaction scores around benefits have jumped 40%. It sells itself."

Angela Russo
Angela Russo
COO · Ontario Digital Service Corp

Layout — Carousel

Avatar fallbacks · initials & icon

When no photo exists, the Avatar falls back to initials, then a generic icon. The avatar type is independent of the layout.

"Joining CAAT was the best HR decision we ever made. Our employees feel secure about their future, and that shows in retention."

Tom Kirkwood
VP People & Culture · GreenTech Solutions

"The CAAT team walked us through every step of onboarding. Our staff had questions answered within days, not weeks."

Anonymous Member
2024 Member Satisfaction Survey

1. Summary

Component pathcaat/components/testimonial
Status New
PurposeDisplay member quotes and testimonials to build trust and social proof, showcasing real experiences from CAAT pension plan members and employer partners.
TierComposite — composes Avatar
VariantsLayout: single · grid · carousel  ·  Avatar: photo · initials · icon  ·  optional star rating (independent axes)
Allowed onHomepage, About, Employers, Member Stories, Landing Pages

2. Design Tokens

TokenValueUsage
--caat-color-bg-page#fffCard background
--caat-color-bordergrey-200Card border (1px, all sides)
--caat-radius.75remCard border radius
--caat-shadow-smCard elevation
--caat-color-textinkQuote text (italic, 1.1rem)
--caat-color-text-heading / --caat-color-text-mutedblue-900 / mutedAttribution name / role
--caat-warning#efaa39Star rating
--caat-color-action-primary / -hoverblue-900 / blue-700Carousel controls + indicators (hover darkens)
Avatar sizing/colours are inherited from the composed Avatar component (48px).

3. Authoring Fields

FieldTypeRequiredNotes
Quote TextRich TextYesThe testimonial body. Supports bold/italic. Max 300 characters recommended.
Attribution NameTextYesFull name of the person providing the testimonial.
Attribution RoleTextNoJob title or role of the quoted person (e.g., "Retired Educator").
Employer NameTextNoOrganization/employer name (e.g., "Durham College").
Avatar ImageImageNoHeadshot, rendered 48×48px via the Avatar component. Falls back to initials, then a generic icon, if empty.
Star RatingNumber (1–5)NoOptional star rating displayed above the quote. Omit to hide rating.
Display VariantSelectYesOptions: single | carousel | grid

4. Validation Rules

FieldRule
Quote TextRequired. Non-empty. Max 500 characters.
Attribution NameRequired. Non-empty. Max 100 characters.
Avatar ImageIf provided: min 128×128px, max 1 MB, formats JPG/PNG/WebP.
Star RatingIf provided: integer between 1 and 5 inclusive.
Carousel variantRequires minimum 2 testimonial items, maximum 8.
Grid variantRequires minimum 2 testimonial items, maximum 6.

5. Content Guidance

  • Authenticity: Use real quotes from real members/employers. Obtain written consent before publishing.
  • Pension-relevant: Focus on retirement security, defined benefit advantages, peace of mind, inflation protection, and employer recruitment benefits.
  • Length: Keep quotes concise — 1–3 sentences (under 300 characters) for maximum impact.
  • Diversity: Represent a variety of roles, institutions, genders, and retirement stages.
  • Attribution: Always include at minimum a name. Role and employer add credibility.
  • Avoid: Specific dollar amounts, investment returns, or language that could constitute financial advice.

6. Semantic HTML

<!-- Single testimonial -->
<div class="caat-testimonial"
     data-analytics-component="testimonial"
     data-analytics-variant="single">
  <blockquote class="caat-testimonial__quote">
    <p>"Quote text here..."</p>
  </blockquote>
  <div class="caat-testimonial__attribution">
    <img class="caat-avatar"
         src="/path/to/avatar.jpg"
         alt="Photo of [Name]"
         width="64" height="64">
    <div>
      <strong>[Name]</strong><br>
      <span class="text-muted">[Role] · [Employer]</span>
    </div>
  </div>
</div>

<!-- Carousel wrapper -->
<div class="caat-testimonial-carousel carousel slide"
     data-bs-ride="false"
     aria-roledescription="carousel"
     aria-label="Member testimonials">
  <div class="carousel-inner">
    <div class="carousel-item active"
         role="group"
         aria-roledescription="slide"
         aria-label="Testimonial 1 of N">
      <!-- .caat-testimonial inside -->
    </div>
  </div>
  <!-- prev/next controls -->
</div>

<!-- Grid wrapper -->
<div class="caat-testimonial-grid">
  <!-- multiple .caat-testimonial children -->
</div>

7. CSS Contract

ClassElementNotes
.caat-testimonialRoot wrapperSingle testimonial card/block. Contains quote + attribution.
.caat-testimonial__quote<blockquote>Styled with left border accent, larger font, italic styling.
.caat-avatarAvatarComposed component — 48px circle (photo / initials / icon). No avatar CSS in this component.
.caat-testimonial__name / __roleAttributionName (heading colour, 700) / role (muted) — now used by the markup.
.caat-testimonial__attributionAttribution rowFlex row with avatar + name/role stack.
.caat-testimonial-carouselCarousel wrapperExtends Bootstrap carousel with CAAT styling.
.caat-testimonial-gridGrid wrapperCSS Grid, 1 col mobile → 2 cols tablet → 3 cols desktop.

8. Accessibility

RequirementImplementation
Blockquote semanticsUse native <blockquote> element so assistive tech announces quoted text.
Avatar alt textProvide descriptive alt: "Photo of [Name]". Use empty alt (alt="") if decorative.
Carousel — keyboardPrevious/Next buttons are keyboard-focusable. Indicators are <button> elements.
Carousel — pause/stopSet data-bs-ride="false" (no autoplay). If autoplay is enabled, provide a visible Pause button.
Carousel — ARIAaria-roledescription="carousel" on wrapper; aria-roledescription="slide" + aria-label on each item.
Reduced motion@media (prefers-reduced-motion: reduce) disables carousel transitions and any fade animations.
Color contrastQuote text and attribution meet WCAG 2.1 AA (4.5:1 minimum).
Star ratingIf present, include visually hidden text: "Rated X out of 5 stars" for screen readers.

9. SEO

  • Testimonials may optionally emit Schema.org Review structured data (@type: Review, author, reviewBody).
  • Ensure quote text is rendered in the DOM (not injected via JS) for crawlability.
  • Use semantic <blockquote> — search engines treat these as quoted content.
  • Avatar images should have descriptive alt attributes that include the person's name.

10. Analytics

Analytics are captured through the shared data-analytics-component attribute on the component root (emitted automatically) and reported to the central data layer. Event names and payloads follow the organisation's standard analytics schema — defined centrally with the analytics team, not invented per component — so no bespoke tracking is specified here.

11. AEM Implementation Notes

  • Resource type: caat/components/testimonial
  • Sling Model: com.caat.core.models.Testimonial — exposes quote, attribution, avatar, rating, variant.
  • Multifield: Carousel and Grid variants use an AEM Multifield to allow authors to add 2–8 testimonial items.
  • Content Fragment support: Optionally bind to a CF model caat/models/testimonial for headless delivery.
  • Policies: Restrict display variant options per template (e.g., only "grid" on homepage).
  • Experience Fragment: Component can be placed in XF for shared testimonial blocks across pages.

12. Dialog Model

Simplified model — shows field intent and Granite UI resource types, not the literal cq:dialog node tree (e.g. select options are authored as child items nodes).

{
  "jcr:primaryType": "nt:unstructured",
  "sling:resourceType": "cq/gui/components/authoring/dialog",
  "jcr:title": "Testimonial",
  "content": {
    "items": {
      "tabs": {
        "items": {
          "testimonialTab": {
            "jcr:title": "Testimonial",
            "items": {
              "variant": {
                "sling:resourceType": "granite/ui/components/coral/foundation/form/select",
                "fieldLabel": "Display Variant",
                "name": "./variant",
                "required": true,
                "options": ["single", "carousel", "grid"]
              },
              "testimonials": {
                "sling:resourceType": "granite/ui/components/coral/foundation/form/multifield",
                "fieldLabel": "Testimonials",
                "composite": true,
                "items": {
                  "quoteText": { "sling:resourceType": "cq/gui/components/authoring/dialog/richtext", "fieldLabel": "Quote", "name": "./quoteText" },
                  "attributionName": { "sling:resourceType": "granite/ui/components/coral/foundation/form/textfield", "fieldLabel": "Name", "name": "./attributionName", "required": true },
                  "attributionRole": { "sling:resourceType": "granite/ui/components/coral/foundation/form/textfield", "fieldLabel": "Role", "name": "./attributionRole" },
                  "employerName": { "sling:resourceType": "granite/ui/components/coral/foundation/form/textfield", "fieldLabel": "Employer", "name": "./employerName" },
                  "avatarImage": { "sling:resourceType": "cq/gui/components/authoring/dialog/fileupload", "fieldLabel": "Avatar", "name": "./avatarImage" },
                  "starRating": { "sling:resourceType": "granite/ui/components/coral/foundation/form/numberfield", "fieldLabel": "Rating (1-5)", "name": "./starRating", "min": 1, "max": 5 }
                }
              }
            }
          }
        }
      }
    }
  }
}

13. QA Acceptance Checklist

  • All three variants (single, carousel, grid) render correctly.
  • Blockquote semantic HTML is present in DOM.
  • Avatar falls back gracefully when no image is provided.
  • Carousel: prev/next/indicator buttons work via keyboard.
  • Carousel does NOT autoplay by default.
  • Reduced-motion media query disables transitions.
  • Grid is responsive: 1 col → 2 cols → 3 cols.
  • Star rating (if present) has visually hidden accessible text.
  • Analytics events fire: testimonial-viewed, carousel-interaction.
  • Cross-browser tested (Chrome, Firefox, Safari, Edge).
  • Content contrast meets WCAG 2.1 AA (4.5:1 for text).

14. Definition of Done

AreaDone means
Design Figma component matches this contract. All three variants are documented. Tokens are used — no hard-coded colour values.
Development AEM proxy component created under caat/components/testimonial. HTL template emits semantic HTML per Section 6. CSS uses design tokens. JS wires analytics events. Unit tests pass.
QA All items in the QA Acceptance Checklist (Section 13) pass. Manual accessibility audit completed. Cross-browser tested.
Launch Component deployed to AEM production. Content authors trained. Documentation published. Analytics dashboards confirmed receiving events.