@shopify/polaris
Version:
Shopify’s product component library
75 lines (74 loc) • 3.4 kB
JavaScript
import React, { useState, useCallback, useEffect } from 'react';
import { classNames, variationName } from '../../utilities/css';
import { useFeatures } from '../../utilities/features';
import { useI18n } from '../../utilities/i18n';
import { useIsAfterInitialMount } from '../../utilities/use-is-after-initial-mount';
import { Image } from '../Image';
import styles from './Avatar.scss';
var Status;
(function (Status) {
Status["Pending"] = "PENDING";
Status["Loaded"] = "LOADED";
Status["Errored"] = "ERRORED";
})(Status || (Status = {}));
export const STYLE_CLASSES = ['one', 'two', 'three', 'four', 'five'];
export function Avatar({ name, source, initials, customer, size = 'medium', accessibilityLabel, }) {
const i18n = useI18n();
const { newDesignLanguage } = useFeatures();
const isAfterInitialMount = useIsAfterInitialMount();
function styleClass(name) {
const finalStyleClasses = newDesignLanguage
? STYLE_CLASSES
: [...STYLE_CLASSES, 'six'];
return name
? finalStyleClasses[name.charCodeAt(0) % finalStyleClasses.length]
: finalStyleClasses[0];
}
const [status, setStatus] = useState(Status.Pending);
// If the source changes, set the status back to pending
useEffect(() => {
setStatus(Status.Pending);
}, [source]);
const handleError = useCallback(() => {
setStatus(Status.Errored);
}, []);
const handleLoad = useCallback(() => {
setStatus(Status.Loaded);
}, []);
const hasImage = source && status !== Status.Errored;
const nameString = name || initials;
let label;
if (accessibilityLabel) {
label = accessibilityLabel;
}
else if (name) {
label = name;
}
else if (initials) {
const splitInitials = initials.split('').join(' ');
label = i18n.translate('Polaris.Avatar.labelWithInitials', {
initials: splitInitials,
});
}
else {
label = i18n.translate('Polaris.Avatar.label');
}
const className = classNames(styles.Avatar, size && styles[variationName('size', size)], !customer && styles[variationName('style', styleClass(nameString))], (hasImage || (initials && initials.length === 0)) &&
status !== Status.Loaded &&
styles.hidden, hasImage && styles.hasImage);
const imageMarkUp = source && isAfterInitialMount && status !== Status.Errored ? (<Image className={styles.Image} source={source} alt="" role="presentation" onLoad={handleLoad} onError={handleError}/>) : null;
// Use `dominant-baseline: central` instead of `dy` when Edge supports it.
const verticalOffset = '0.35em';
const avatarBody = customer || !initials ? (<path fill="currentColor" d="M8.28 27.5A14.95 14.95 0 0120 21.8c4.76 0 8.97 2.24 11.72 5.7a14.02 14.02 0 01-8.25 5.91 14.82 14.82 0 01-6.94 0 14.02 14.02 0 01-8.25-5.9zM13.99 12.78a6.02 6.02 0 1112.03 0 6.02 6.02 0 01-12.03 0z"/>) : (<text x="50%" y="50%" dy={verticalOffset} fill="currentColor" fontSize="20" textAnchor="middle">
{initials}
</text>);
const svgMarkup = !hasImage ? (<span className={styles.Initials}>
<svg className={styles.Svg} viewBox="0 0 40 40">
{avatarBody}
</svg>
</span>) : null;
return (<span aria-label={label} role="img" className={className}>
{svgMarkup}
{imageMarkUp}
</span>);
}