Testimonial
A testimonial is a quotation with an attribution, and that is exactly what
<x-wirekit::testimonial> renders: a <figure> wrapping a <blockquote> and a
<figcaption>. A screen reader announces it as a quote and reads the attribution
as belonging to it — which a stack of styled <div>s never does, however much it
looks the part.
-
We replaced four hand-built components with one and the accessibility review came back clean on the first pass.
Ada Lovelace Ada Lovelace Principal Engineer, Analytical -
The parts I usually have to fight — focus order, keyboard traps, dark mode — were simply already right.
Grace Hopper Grace Hopper CTO, Compiler Works -
Every component takes tokens, so our whole brand landed by editing one file. No forks, no overrides.
Alan Turing Alan Turing Head of Platform, Enigma
Attribution
author is what makes a testimonial a testimonial. role adds the context that
makes it persuasive.
Without an avatar, the component derives the author's initials and renders
them in a deterministic color rather than showing an empty gray disc — the same
person always gets the same color. Pass initials yourself for a mononym, a
brand account, or any name where first-and-last-letter is the wrong reading.
{{-- Photo --}}
<x-wirekit::testimonial author="Ada Lovelace" role="Principal Engineer" avatar="/img/ada.jpg">
…
</x-wirekit::testimonial>
{{-- No photo — initials are derived ("AL") --}}
<x-wirekit::testimonial author="Ada Lovelace" role="Principal Engineer">
…
</x-wirekit::testimonial>
{{-- Override the derived initials --}}
<x-wirekit::testimonial author="Björk" initials="B">
…
</x-wirekit::testimonial>
Rating
rating renders a read-only star rating above the quote. It is a record of what
someone gave, never an input — the stars are not focusable and cannot be changed.
<x-wirekit::testimonial author="Grace Hopper" :rating="5">
…
</x-wirekit::testimonial>
Company logo
logo places a company mark at the end of the attribution.
Leave logo-alt unset when the author is already named in text: the logo is then
decoration, and giving it a name only makes a screen reader read the company
twice. Pass logo-alt when the logo is the only attribution.
{{-- Author named in text -> the logo is decorative and stays silent --}}
<x-wirekit::testimonial author="Alan Turing" role="Head of Platform, Enigma" logo="/img/enigma.svg">
…
</x-wirekit::testimonial>
{{-- Logo carries the attribution on its own -> name it --}}
<x-wirekit::testimonial author="" logo="/img/enigma.svg" logo-alt="Enigma">
…
</x-wirekit::testimonial>
The grid
<x-wirekit::testimonial-grid> is a labeled list — a real <ul> whose
children are <li> elements. That is not decoration: it means a screen reader
announces "list, 3 items" before the quotes, so someone who cannot see the row
knows how many there are to get through.
It flows one column on a phone, two on a tablet, three on a desktop, and stretches every quote to the height of the tallest so the row keeps a clean baseline however uneven the copy is.
<x-wirekit::testimonial-grid label="What developers say">
<li>
<x-wirekit::testimonial author="Ada Lovelace">…</x-wirekit::testimonial>
</li>
<li>
<x-wirekit::testimonial author="Grace Hopper">…</x-wirekit::testimonial>
</li>
</x-wirekit::testimonial-grid>
Props
<x-wirekit::testimonial>
| Prop | Type | Default | Description |
|---|---|---|---|
author |
string |
'' |
Who said it. |
role |
string|null |
null |
Their role / company. |
avatar |
string|null |
null |
Author photo URL. Omit to render derived initials. |
initials |
string|null |
null |
Override the derived initials. |
logo |
string|null |
null |
Company logo URL. |
logoAlt |
string|null |
null |
Accessible name for the logo. Omit when the author is named in text. |
rating |
int|float|null |
null |
Read-only star rating (0–5). |
scope |
string|null |
null |
Class-scope override. |
<x-wirekit::testimonial-grid>
| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
'Testimonials' |
Accessible name for the list of quotes. |
scope |
string|null |
null |
Class-scope override. |
Accessibility
- The quote is a real
<blockquote>inside a<figure>, attributed by a<figcaption>— announced as a quotation with its source, not as loose text. - The grid is a labeled
<ul role="list">of<li>items, so the number of quotes is announced up front. - The star rating is read-only and not focusable — it is a record, not a control.
- A decorative company logo renders
alt=""and is skipped, so the company is not announced twice when the author already names it. - Initials are derived with multibyte-safe string handling, so a non-ASCII name is never sliced mid-codepoint.
Keyboard Interaction
None. A testimonial is content, not a control — there is nothing here to operate. The read-only star rating is deliberately not focusable, so tabbing through a wall of quotes never traps a keyboard user in decorative stars. Any link you place inside the quote keeps its own normal tab behavior.