Skip to content

Support Next.js Image in Avatar slots API without TypeScript errors #45443

Open
@Demianeen

Description

@Demianeen

Summary

Problem
MUI’s slots API for Avatar allows replacing the default element, for example:

import Image from 'some-other-image'

<Avatar slots={{ img: Image }} />

However, Next.js <Image> is not a drop-in replacement for <img>. It requires additional props (alt, width, height, etc.) and has a different src type (string | StaticImport), leading to a TypeScript mismatch when used in the slots.img prop.

For example, this code works at runtime, but throws TypeScript error that img and Image types not match:

<Avatar
	src={company.logoUrl ? company.logoUrl : undefined}
	slots={{
		img: Image,
	}}
	slotProps={{
		img: {
			width: 164,
			height: 164,
		},
	}}
	sx={{ width: 164, height: 164 }}
/>

We can't do the type augmentation either, because then we get an typescript error that Subsequent property declarations must have the same type.

Workaround

As a temporary workaround I created AppAvatar that handles the mui Avatar and Next Image integration and added mui Avatar to restricted-imports:

// AppAvatar.tsx
import type { AvatarProps } from '@mui/material'
// eslint-disable-next-line no-restricted-imports
import { Avatar } from '@mui/material'
import Image from 'next/image'

export interface AppAvatarProps {
	src?: string
	alt: string
	width?: number
	height?: number
}

export function AppAvatar<
	RootComponent extends React.ElementType = 'div',
	AdditionalProps = object,
>({
	src,
	alt,
	width = 40,
	height = 40,
	sx,
	...props
}: AppAvatarProps & AvatarProps<RootComponent, AdditionalProps>) {
	return (
		<Avatar
			sx={{
				width: width,
				height: height,
				...sx,
			}}
			{...props}
		>
			{src && <Image src={src} width={width} height={height} alt={alt} />}
		</Avatar>
	)
}
// eslint.config.mjs
'no-restricted-imports': [
	2,
	...
	{
		name: '@mui/material',
		importNames: ['Avatar'],
		message: 'Please use `@/shared/ui/AppAvatar` instead.',
	},
	{
		name: '@mui/material/Avatar',
		message: 'Please use `@/shared/ui/AppAvatar` instead.',
	},
]

It would be good improve mui’s slots API to better support different usecases like Next.js <Image> to improve next.js integration

Related:
#45404

Examples

No response

Motivation

Integrating Next.js <Image> with MUI's <Avatar> is a common use case for Next.js projects that use mui. However, the current slots API does not support it natively, requiring workarounds.

Plus generally different solutions may have a slightly different apis, and while they work with mui at runtime, they still produce type errors. It would be really beneficial to have the ability to expand the slot props with custom overrides

Search keywords: Next Image NextImage

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🐛Something doesn't workcomponent: avatarThis is the name of the generic UI component, not the React module!customization: domComponent's DOM customizability, e.g. slottypescript

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions