question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`fragment` tag for composition

See original GitHub issue

Problem

Currently it’s not possible to compose styles from multiple classnames together. Previously we had a include helper which would take a class name and return the unprocessed CSS text. I removed it because it wasn’t strightforward to implement it with the new approach and I haven’t needed to use it personally. In addition, an extra class name was generated whether you used it anywhere or not.

Another usecase is that once you get into an interpolation inside the tagged template, we don’t parse the nested interpolations. So it’s not possible to do something like following:

const Box = styled.div`
  font-size: 14px;

  ${borders
    .map(({ p, w }) => `border-${p}: ${w}px solid ${props => props.color}`)
    .join('\n')};
`;

styled-components has exports css tag to support this. However, the css tag is used for class names in Linaria, so we can’t do the same.

Prior art

Emotion allows you to interpolate a class name which inlines its styles: https://emotion.sh/docs/composition

One problem with this approach is that you’re interpolating a class name, but getting the CSS text instead. This breaks the following use case where you might want to refer to another class name:

const paragraph = css`
  font-size: 14px;
`;

const article = css`
  backgrounc-color: white;

  .${paragraph} {
    font-size: 16px;
  }
`;

Current solution

Currently, you could do something like this:

const shared = `
  font-size: 18px;
`;

const Title = styled.h1`
  ${shared};

  color: black;
`;

There are 2 issues with this approach:

  1. There’s no syntax highlighting or autocomplete for the CSS
  2. It’s not possibe to use dynamic interpolations like you would in styled

Proposal

We could add a new fragment tag to allow this use case:

const shared = fragment.css`
  font-size: 18px;
`;

const Title = styled.h1`
  ${shared};

  color: black;
`;

The fragment tag itself won’t generate any class names, but when the result is interpolated, it will inline the CSS text along with the dynamic interpolations. It’ll work very similarly to how styled-components handles interpolation of css tagged template literals. As for parsing, it would be parsed similar to how the styled.x tags are parsed.

Note: Initially I thought of having just fragment, but went for fragment.css since it allows us to have syntax highlighting and autocomplete.

Since the fragment tag won’t generate a class name, to use it as a class, you could do something like this:

const title = css`${shared}`;

You could even inline it if you don’t like creating an extra variable:

<h1 class={css`${shared}`} />

Why not add it

It requires extra code, especially if we want to support interpolations and don’t want to leave the CSS code for the fragment inside the JS bundle.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:47
  • Comments:30 (15 by maintainers)

github_iconTop GitHub Comments

13reactions
jayucommented, May 19, 2020

I opened a draft PR with PoC implementation, the allowed syntax is as below, please find the description in the PR #615

const fragment = css`
  color: red;
  font-size: 40px;
  padding-top: ${(props) => props.height || '200px'}; 
`

const anotherFragment = css`
  color: yellow;
  ${fragment};
  border: 10px solid black;
`

const component styled.h1`
color: black;
${anotherFragment}
.sub-class {
    ${fragment}
}
`
4reactions
jayucommented, Apr 4, 2020

Styles composition would be extremely useful once we introduce react-native support #236 We could potentially share more code between react and react-native

Read more comments on GitHub >

github_iconTop Results From Across the Web

Fragments - Apollo GraphQL Docs
A GraphQL fragment is a piece of logic that can be shared between multiple queries and mutations. ... Every fragment includes a subset...
Read more >
Fragments - React
A common pattern in React is for a component to return multiple elements. Fragments let you group a list of children without adding...
Read more >
Interoperability APIs | Jetpack Compose - Android Developers
Fragments. The Composition must follow the fragment's view lifecycle for Compose UI View types to save state. Transitions. Anytime the Compose UI View ......
Read more >
Fragments | Relay
Relay guide to rendering fragments. ... In order to declare a fragment inside your JavaScript code, you must use the graphql tag: ......
Read more >
How to use Compose inside Fragment? - Stack Overflow
setViewCompositionStrategy (DisposeOnViewTreeLifecycleDestroyed) in addition the composition strategy should be reviewed when doing this.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found