Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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

Open
Demianeen opened this issue Feb 28, 2025 · 1 comment
Open

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

Demianeen opened this issue Feb 28, 2025 · 1 comment
Labels
component: avatar This is the name of the generic UI component, not the React module! customization: dom Component's DOM customizability, e.g. slot enhancement This is not a bug, nor a new feature typescript

Comments

@Demianeen
Copy link

Demianeen commented Feb 28, 2025

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

@Demianeen Demianeen added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Feb 28, 2025
@siriwatknp siriwatknp added component: avatar This is the name of the generic UI component, not the React module! typescript enhancement This is not a bug, nor a new feature customization: dom Component's DOM customizability, e.g. slot and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Mar 3, 2025
@siriwatknp
Copy link
Member

Thanks for the feedback, I'll try to find a proper solution for this.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
component: avatar This is the name of the generic UI component, not the React module! customization: dom Component's DOM customizability, e.g. slot enhancement This is not a bug, nor a new feature typescript
Projects
None yet
Development

No branches or pull requests

2 participants