Summary
In Hero variant="gridline-expressive", any child that isn't a recognized sub-component (Hero.Heading, Hero.Description, Hero.PrimaryAction/SecondaryAction, Hero.Image/Video, Hero.Label, Hero.Eyebrow) is silently dropped from the rendered output. There's no slot or prop for putting decorative content (e.g. a background layer) inside Hero-imageWrapper.
Use case
Marketing Engineering: https://github.com/github/marketing-engineering/issues/5476
We want a WebGLDither background sitting behind Hero.Image in the gridline-expressive variant. The dither is a <div> that registers with a parent WebGL context, so it has to be a real DOM element inside the image wrapper.
<Hero variant="gridline-expressive">
<Hero.Heading>…</Hero.Heading>
<Hero.Image src="…" alt="" />
<WebGLDither … /> {/* silently dropped */}
</Hero>
Proposal
Provide a supported way to inject content into Hero-imageWrapper. Any of:
- A new
<Hero.ImageBackground> slot (or an imageBackground prop) rendered as the first child of Hero-imageWrapper.
- Render the existing "other children" bucket inside
Hero-imageWrapper for all variants.
- At minimum, accept callback refs on
imageContainerRef and add a CSS hook that opts Hero-imageWrapper into position: relative; isolation: isolate; background-color: transparent; so the portal workaround below isn't fragile.
Current workaround
const [el, setEl] = useState<HTMLDivElement | null>(null)
const ref = useMemo(() => ({
get current() { return el },
set current(v) { if (v !== el) setEl(v) },
}), [el])
return (
<>
<Hero
variant="gridline-expressive"
imageContainerRef={ref}
imageContainerClassName={styles.heroImageWrapper}
>
…
<Hero.Image … />
</Hero>
{el && createPortal(<WebGLDither … />, el)}
</>
)
Summary
In
Hero variant="gridline-expressive", any child that isn't a recognized sub-component (Hero.Heading,Hero.Description,Hero.PrimaryAction/SecondaryAction,Hero.Image/Video,Hero.Label,Hero.Eyebrow) is silently dropped from the rendered output. There's no slot or prop for putting decorative content (e.g. a background layer) insideHero-imageWrapper.Use case
Marketing Engineering: https://github.com/github/marketing-engineering/issues/5476
We want a
WebGLDitherbackground sitting behindHero.Imagein the gridline-expressive variant. The dither is a<div>that registers with a parent WebGL context, so it has to be a real DOM element inside the image wrapper.Proposal
Provide a supported way to inject content into
Hero-imageWrapper. Any of:<Hero.ImageBackground>slot (or animageBackgroundprop) rendered as the first child ofHero-imageWrapper.Hero-imageWrapperfor all variants.imageContainerRefand add a CSS hook that optsHero-imageWrapperintoposition: relative; isolation: isolate; background-color: transparent;so the portal workaround below isn't fragile.Current workaround