Description
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