Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ce76106
feat(avatar): add pf-v6-avatar element
zeroedin May 8, 2026
4f20b21
fix(avatar): apply review fixes
zeroedin May 8, 2026
3a48a5e
docs(avatar): align demos to react
zeroedin May 8, 2026
029d18d
fix(avatar): correct css vars
zeroedin May 8, 2026
47ea912
fix(avatar): readd typing
zeroedin May 8, 2026
c76f5d8
Merge branch 'staging/pfv6' into feat/v6-avatar
zeroedin May 12, 2026
fbbd713
chore: remove pf-v5-avatar
zeroedin May 13, 2026
eef757f
fix(avatar): correct jsdoc to cem documentation comments
zeroedin May 13, 2026
7c1346f
chore: add changeset
zeroedin May 13, 2026
32a5166
Merge branch 'staging/pfv6' into feat/v6-avatar
zeroedin May 14, 2026
1eac98a
docs(avatar): add README
zeroedin May 14, 2026
f257006
docs(avatar): improve README documentation
zeroedin May 19, 2026
68e925a
test(avatar): improve tests
zeroedin May 19, 2026
d1139f7
docs(avatar): add missing docs markdown and screenshot
zeroedin May 19, 2026
9285164
test(avatar): add missing e2e test file
zeroedin May 19, 2026
474a506
Merge remote-tracking branch 'origin/staging/pfv6' into feat/v6-avatar
bennypowers May 27, 2026
fc814e7
chore(avatar): update readme
zeroedin Jun 12, 2026
5a55db9
docs: update avatar import reference
zeroedin Jun 12, 2026
b7837d9
Merge branch 'staging/pfv6' into feat/v6-avatar
bennypowers Jun 15, 2026
0b1fa19
docs: jsdoc
bennypowers Jun 15, 2026
fa1669e
fix!: remove load event
bennypowers Jun 15, 2026
24d734a
perf: simplify template
bennypowers Jun 15, 2026
22e860c
test: replace load element with nextFrame
bennypowers Jun 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions elements/pf-v6-avatar/demo/avatarImg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions elements/pf-v6-avatar/demo/basic.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: Basic
description: A basic avatar displays a user image.
---
<pf-v6-avatar alt="Avatar image"
src="./avatarImg.svg"></pf-v6-avatar>

<script type="module">
import '@patternfly/elements/pf-v6-avatar/pf-v6-avatar.js';
</script>
19 changes: 19 additions & 0 deletions elements/pf-v6-avatar/demo/bordered.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: Bordered
description: A bordered avatar has a thin border around the image.
---
<section>
<pf-v6-avatar bordered
alt="Bordered avatar"
src="./avatarImg.svg"></pf-v6-avatar>
</section>

<script type="module">
import '@patternfly/elements/pf-v6-avatar/pf-v6-avatar.js';
</script>

<style>
section {
padding: 64px 48px;
}
</style>
9 changes: 9 additions & 0 deletions elements/pf-v6-avatar/demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name: Basic
description: A basic avatar displays a user image.
---
<pf-v6-avatar></pf-v6-avatar>

<script type="module">
import '@patternfly/elements/pf-v6-avatar/pf-v6-avatar.js';
</script>
63 changes: 63 additions & 0 deletions elements/pf-v6-avatar/demo/size-variations.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
name: Size variations
description: Avatars can be displayed in four sizes.
---
<dl>
<div>
<dt>Small</dt>
<dd>
<pf-v6-avatar size="sm"
alt="Small avatar"
src="./avatarImg.svg"></pf-v6-avatar>
</dd>
</div>

<div>
<dt>Medium</dt>
<dd>
<pf-v6-avatar size="md"
alt="Medium avatar"
src="./avatarImg.svg"></pf-v6-avatar>
</dd>
</div>

<div>
<dt>Large</dt>
<dd>
<pf-v6-avatar size="lg"
alt="Large avatar"
src="./avatarImg.svg"></pf-v6-avatar>
</dd>
</div>

<div>
<dt>Extra Large</dt>
<dd>
<pf-v6-avatar size="xl"
alt="Extra large avatar"
src="./avatarImg.svg"></pf-v6-avatar>
</dd>
</div>
</dl>

<script type="module">
import '@patternfly/elements/pf-v6-avatar/pf-v6-avatar.js';
</script>

<style>
dl {
padding: 64px 48px;
display: flex;
gap: 1em;

& > div {
display: flex;
gap: 1em;
flex-flow: column;
}

& dd {
margin: 0;
}
}
</style>
54 changes: 54 additions & 0 deletions elements/pf-v6-avatar/pf-v6-avatar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
:host {
--_width: var(--pf-v6-c-avatar--Width, 2.25rem);
--_height: var(--pf-v6-c-avatar--Height, 2.25rem);
--_border-radius: var(--pf-v6-c-avatar--BorderRadius, var(--pf-t--global--border--radius--pill, 30em));
--_border-color: var(--pf-v6-c-avatar--BorderColor, transparent);
--_border-width: var(--pf-v6-c-avatar--BorderWidth, 0);
--_placeholder-bg: var(--pf-t--global--background--color--200, light-dark(var(--pf-t--color--gray--10, #f2f2f2), var(--pf-t--color--gray--80, #292929)));
--_placeholder-fg: var(--pf-t--global--icon--color--subtle, light-dark(var(--pf-t--color--gray--50, #707070), var(--pf-t--color--gray--40, #a3a3a3)));

display: inline-block;
width: var(--_width);
height: var(--_height);
border-radius: var(--_border-radius);
}

:host([hidden]),
[hidden] {
display: none !important;
}

:host([bordered]) {
--_border-color: var(--pf-v6-c-avatar--m-bordered--BorderColor, var(--pf-t--global--border--color--default, #d2d2d2));
--_border-width: var(--pf-v6-c-avatar--m-bordered--BorderWidth, var(--pf-t--global--border--width--box--default, 1px));
}

:host([size="sm"]) {
--_width: var(--pf-v6-c-avatar--m-sm--Width, 1.5rem);
--_height: var(--pf-v6-c-avatar--m-sm--Height, 1.5rem);
}

:host([size="md"]) {
--_width: var(--pf-v6-c-avatar--m-md--Width, 2.25rem);
--_height: var(--pf-v6-c-avatar--m-md--Height, 2.25rem);
}

:host([size="lg"]) {
--_width: var(--pf-v6-c-avatar--m-lg--Width, 4.5rem);
--_height: var(--pf-v6-c-avatar--m-lg--Height, 4.5rem);
}

:host([size="xl"]) {
--_width: var(--pf-v6-c-avatar--m-xl--Width, 8rem);
--_height: var(--pf-v6-c-avatar--m-xl--Height, 8rem);
}

svg,
img {
display: block;
object-fit: cover;
width: var(--_width);
height: var(--_height);
border-radius: var(--_border-radius);
border: var(--_border-width) solid var(--_border-color);
}
80 changes: 80 additions & 0 deletions elements/pf-v6-avatar/pf-v6-avatar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { LitElement, html, type TemplateResult } from 'lit';
import { property } from 'lit/decorators/property.js';
import { customElement } from 'lit/decorators/custom-element.js';

import style from './pf-v6-avatar.css';

/** Size variants for the avatar. */
export type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';

export class PfV6AvatarLoadEvent extends Event {
constructor(public originalEvent: Event) {
super('load', { bubbles: true });
}
}

/**
* An **avatar** is a visual used to represent a user. It may contain an image
* or a placeholder graphic.
* @summary Displays a user's avatar image
* @fires {PfV6AvatarLoadEvent} load - when the avatar image loads
* @cssprop {<length>} --pf-v6-c-avatar--Width - Width of the avatar
Comment thread
zeroedin marked this conversation as resolved.
Outdated
* @cssprop {<length>} --pf-v6-c-avatar--Height - Height of the avatar
* @cssprop {<length>} --pf-v6-c-avatar--BorderRadius - Border radius of the avatar
* @cssprop {<color>} --pf-v6-c-avatar--BorderColor - Border color of the avatar
* @cssprop {<length>} --pf-v6-c-avatar--BorderWidth - Border width of the avatar
* @cssprop {<length>} --pf-v6-c-avatar--m-sm--Width - Width when size is `sm`
* @cssprop {<length>} --pf-v6-c-avatar--m-sm--Height - Height when size is `sm`
* @cssprop {<length>} --pf-v6-c-avatar--m-md--Width - Width when size is `md`
* @cssprop {<length>} --pf-v6-c-avatar--m-md--Height - Height when size is `md`
* @cssprop {<length>} --pf-v6-c-avatar--m-lg--Width - Width when size is `lg`
* @cssprop {<length>} --pf-v6-c-avatar--m-lg--Height - Height when size is `lg`
* @cssprop {<length>} --pf-v6-c-avatar--m-xl--Width - Width when size is `xl`
* @cssprop {<length>} --pf-v6-c-avatar--m-xl--Height - Height when size is `xl`
* @cssprop {<color>} --pf-v6-c-avatar--m-bordered--BorderColor - Border color when bordered
* @cssprop {<length>} --pf-v6-c-avatar--m-bordered--BorderWidth - Border width when bordered
*/
@customElement('pf-v6-avatar')
export class PfV6Avatar extends LitElement {
static readonly styles: CSSStyleSheet[] = [style];

/** The URL to the user's custom avatar image. */
@property() src?: string;

/** The alt text for the avatar image. */
@property({ reflect: true }) alt?: string;

/** Size of the avatar */
@property({ reflect: true }) size?: AvatarSize;

/** Whether to display a border around the avatar */
@property({ type: Boolean, reflect: true }) bordered = false;

override render(): TemplateResult {
return this.src != null ? html`
<img id="img"
alt="${this.alt ?? ''}"
src=${this.src}
Comment thread
zeroedin marked this conversation as resolved.
Outdated
@load="${this.#onLoad}">
` : html`
<svg id="placeholder"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 36 36">
<rect width="36" height="36" fill="var(--_placeholder-bg)"/>
<path d="M30.5 36c-.4-3.9-1.3-9-2.9-11-1.1-1.4-2.3-2.2-3.5-2.6s-1.8-.6-6.3-.6-6.1.7-6.1.7c-1.2.4-2.4 1.2-3.4 2.6C6.7 27 5.8 32.2 5.4 36h25.1zM17.7 20.1c-3.5 0-6.4-2.9-6.4-6.4s2.9-6.4 6.4-6.4 6.4 2.9 6.4 6.4-2.8 6.4-6.4 6.4z"
fill="var(--_placeholder-fg)"/>
</svg>
`;
}

#onLoad(event: Event) {
this.dispatchEvent(new PfV6AvatarLoadEvent(event));
}
}

declare global {
interface HTMLElementTagNameMap {
'pf-v6-avatar': PfV6Avatar;
}
}
Loading
Loading