Skip to content

[pigment-css] Support cross-referencing components #41421

Closed
@joshwcomeau

Description

@joshwcomeau

Summary

One of the "killer features" of styled-components, IMO, is the ability to reference one component's class within another component definition.

For example:

const Figure = styled.figure`...`

const Link = styled.a`
  color: blue;
  
  ${Figure} & {
    color: inherit;
  }
`

It would be great if we could do the same thing in Pigment CSS!

Here's what I tried to do:

export default function Home() {
  return (
    <>
      <Wrapper>
        <Button>Inside</Button>
      </Wrapper>

      <Button>Outside</Button>
    </>
  );
}

const Wrapper = styled('div')``;

const Button = styled('button')({
  color: 'red',

  [`${Wrapper} &`]: {
    color: 'blue',
  },
});

This doesn't work, because Wrapper gets stringified to [object Object].

I know that Linaria supports this behaviour, which also uses wyw-in-js, so I know this is possible, but I'm afraid I have no idea how they're accomplishing it 😬.

Repro

CodeSandboxGithub source

Motivation

I know that this might seem like a pretty niche concern, but this pattern is so so important.

A lot of teams solve this by creating a "variant" of a component. For example, maybe we create a FigureLink styled component:

const Link = styled('a')({
  color: 'blue',
});

const FigureLink = styled(Link)({
  color: 'inherit',
});

The problem is that this requires the developer to remember to use FigureLink each and every time they have a link inside a figure. It requires superhuman discipline. Most likely, we'll wind up with a mismatched UI, where some links use FigureLink and others use Link.

Alternatively, we could style based on tag, like:

const Figure = styled('figure')({
  '& a': {
    color: 'inherit',
  }
});

The trouble with this approach is that it "reaches in" to the Link component and meddles with its internal styles. It also means that the styles for the Link component will be sprinkled all across the codebase, making it very difficult to understand the ways in which styles can change.

With the "cross-reference" thing, all of the styles for Link are gathered in 1 place.

Search keywords: Pigment CSS

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions