Add Author Placeholder in Docusaurus
Add anavatar placeholder like this author.
Create a function getInitial()
Create and export this helper function to extract first letter.
src/utils/index.ts
export function getInitial(fullName: string): string {
const words = fullName.trim().split(/\s+/);
if (words.length === 0) return '';
const firstInitial = words[0][0].toUpperCase();
const lastInitial = words.length > 1 ? words[words.length - 1][0].toUpperCase() : '';
return firstInitial + lastInitial;
}
Swizzle a component
We have to swizzle Blog/Components/Author to get a copy of @theme.
pnpm run swizzle @docusaurus/theme-classic Blog/Components/Author --eject
Ternary conditional rendering
This section has 2 parts. First, convert a short-circuit conditional rendering into a ternary operator conditional rendering at imageUrl with a return of null.
src/theme/Blog/Components/Author/index.tsx
// Old
{
imageURL && (
<MaybeLink href={link} className="avatar__photo-link">
<img className={clsx('avatar__photo', styles.authorImage)} src={imageURL} alt={name} />
</MaybeLink>
);
}
// New
{
imageURL ? (
<MaybeLink href={link} className="avatar__photo-link">
<img className={clsx('avatar__photo', styles.authorImage)} src={imageURL} alt={name} />
</MaybeLink>
) : null;
}
Secondly, we will replace null with this code.
src/theme/Blog/Components/Author/index.tsx
<MaybeLink href={link}>
<div className={clsx(styles.authorImage)}>
<div className={clsx(styles.avatarPlaceholder)}>
<span className={clsx(styles.avatarText, styles.authorName)}>{getInitial(author.name)}</span>
</div>
</div>
</MaybeLink>
warning
Don't forget to import getInitial() from utils.
import { getInitial } from '@site/src/utils';
View full code here.
src/theme/Blog/Components/Author/index.tsx
{
imageURL ? (
<MaybeLink href={link} className="avatar__photo-link">
<img className={clsx('avatar__photo', styles.authorImage)} src={imageURL} alt={name} />
</MaybeLink>
) : (
<MaybeLink href={link}>
<div className={clsx(styles.authorImage)}>
<div className={clsx(styles.avatarPlaceholder)}>
<span className={clsx(styles.avatarText, styles.authorName)}>{getInitial(author.name)}</span>
</div>
</div>
</MaybeLink>
);
}
New CSS class
We have to add a new CSS classes. The first one is in custom.css and the others in styles.module.css.
src/css/custom.css
:root {
--ifm-avatar-placeholder-background: var(--ifm-color-primary);
}
src/theme/Blog/Components/Author/styles.module.css
.avatarPlaceholder {
aspect-ratio: 1;
background: var(--ifm-avatar-placeholder-background);
border-radius: 3.40282e38px;
justify-content: center;
align-items: center;
width: var(--ifm-avatar-photo-size);
display: flex;
overflow: hidden;
}
.avatarText {
color: var(--ifm-font-color-base-inverse); /* OR var(--ifm-font-color-base) if you want light-theme color*/
font-weight: 700;
}
We don't have to create styles.authorImage nor styles.authorName because they will interit style from Docusaurus theme classic.
--ifm-avatar-placeholder-backgroundis a background of avatar placeholder. The default is your main theme color.--ifm-avatar-photo-sizeis width and height of avatar placeholder and is passed by.authorImageclassname.font-sizevalue is passed by.authorNameclassname.--ifm-font-color-baseand--ifm-font-color-base-inversecontain a text color for light and dark mode.