Use image module in slotProps

My project uses Tailwind and Material UI.

I am trying to add a background image to an Avatar component. I am able to do it correctly using the slotProps of the Avatar component by adding the full URL of the background image in bg-[url("...")] but I am not able to use that URL with the image module imported in React.

I put together a simple example on codesandbox

import droidbug from "./droidbug.png";
import background from "./background.jpg";

export default function App() {
  return (
    <div className="App">
      <div className="flex items-center">
        Background: <img src={background} width="50px" />
      </div>
      <AvatarGroup>
        <Avatar
          src={droidbug}
          alt="droid"
          slotProps={{
            img: {
              className:
                "bg-[url(https://uploads.codesandbox.io/uploads/user/5933fafc-2c28-466e-be86-43329df70aa1/V8Vl-001_simple_starry_profile_skin_by_volpheus_dg0v53a-fullview.jpg)]",
            },
          }}
        />
        <Avatar
          src={droidbug}
          alt="droid"
          slotProps={{
            img: {
              className: "bg-[url({background})]",
            },
          }}
        />
      </AvatarGroup>
    </div>
  );
}

The first Avatar is displaying the background image correctly, the second does not and when inspecting, it has class= bg-[url({background})]" which is obviously incorrect.

Changing to className: "bg-[url("+{background}+")]", sets it to class="bg-[url([object Object])]" which is not much better

Tailwind can only recognize complete unbroken class names determined at compile time. For dynamically determined resources, they should be specified directly using style.

import "./styles.css";
import { Avatar, AvatarGroup } from "@mui/material";

import droidbug from "./droidbug.png";
import background from "./background.jpg";

export default function App() {
  return (
    <div className="App">
      <div className="flex items-center">
        Background: <img src={background} width="50px" />
      </div>
      <AvatarGroup>
        <Avatar
          src={droidbug}
          alt="droid"
          slotProps={{
            img: {
              className:
                "bg-[url(https://uploads.codesandbox.io/uploads/user/5933fafc-2c28-466e-be86-43329df70aa1/V8Vl-001_simple_starry_profile_skin_by_volpheus_dg0v53a-fullview.jpg)]",
            },
          }}
        />
        <Avatar
          src={droidbug}
          alt="droid"
          slotProps={{
            img: {
              style: {
                background: `url(${background})`,
              },
            },
          }}
        />
      </AvatarGroup>
    </div>
  );
}

Issue

You’ve coded the string literal "bg-[url({background})]".

"bg-[url("+{background}+")]" also fails because it uses string concatenation which implicitly calls the .toString method of the object reference, thus resulting in that "bg-[url([object Object])]" string literal.

const background = "../path/to/resource.jpg";
console.log("bg-[url(${background})]");    // "bg-[url(${background})]"
console.log("bg-[url("+{background}+")]"); // "bg-[url([object Object])]"

Expand snippet

Solution

Use a template literal instead to inject the background resource URL path.

const background = "../path/to/resource.jpg";
console.log(`bg-[url(${background})]`); // "bg-[url(../path/to/resource.jpg)]"

Expand snippet

<Avatar
  src={droidbug}
  alt="droid"
  slotProps={{
    img: {
      className: `bg-[url(${background})]`,
    },
  }}
/>