cssinjs / styled-jss

Styled Components on top of JSS.
http://cssinjs.org/styled-jss
MIT License
217 stars 25 forks source link

Components selectors #40

Closed goodmind closed 6 years ago

goodmind commented 6 years ago

Is this possible with styled-jss?

const AuthorName = styled('div')({...})
const Avatar = styled('img')({...})

const Message = styled('div')({
  [`&:not(:first-child) ${AuthorName}`]: {
    display: 'none'
  },
  [`&:not(:last-child) ${Avatar}`]: {
    visibility: 'hidden'
  }
})
lttb commented 6 years ago

Hi @goodmind!

We have not supported this yet, but it looks like a good case.

I'll try to implement this soon 👍

lttb commented 6 years ago

But we're open for PR of course 😄

goodmind commented 6 years ago

@lttb it looks like className is generated only when component is rendered, so we can't add some magic toString function to component itself

lttb commented 6 years ago

@lttb it looks like className is generated only when component is rendered, so we can't add some magic toString function to component itself

not exactly, let me explain how it works

we can separate properties on static and dynamic values (function values).

static values are the same for each instance, and we can use just one classname for all instances, so we generate classname for static properties immediately and share it for all instances of created styled component.

but if we have function values, we need to have its' own classname of dynamic values for each instance, that's why we generate dynamic classname in the constructor.

therefore with 1st and 3d cases we can use static classname in toString.

But I don't want to generate additional static classname in the 2nd case. The possible solution is that we can generate it in lazy mode, just on toString call for example, if we don't have static classname yet.

And, just to note, the possible temporary workaround may look like this:

const styled = Styled({
  message: {
      '&:not(:first-child) $AuthorName': {
        display: 'none'
      },
      '&:not(:last-child) $StyledPeerPhoto': {
        visibility: 'hidden'
      }
  }
})

const MyAuthorName = styled(AuthorName)({composes: '$AuthorName'})
const MyAvatar = styled(Avatar)({composes: '$StyledPeerPhoto'})
const Message = styled('div')({composes: '$message'})
lttb commented 6 years ago

And, just to note, the possible temporary workaround may look like this:

const styled = Styled({
  message: {
      '&:not(:first-child) $AuthorName': {
        display: 'none'
      },
      '&:not(:last-child) $StyledPeerPhoto': {
        visibility: 'hidden'
      }
  }
})

const MyAuthorName = styled(AuthorName)({composes: '$AuthorName'})
const MyAvatar = styled(Avatar)({composes: '$StyledPeerPhoto'})
const Message = styled('div')({composes: '$message'})

You can check an example here: https://www.webpackbin.com/bins/-KrDP1-pNR8ddDXK-gR5

goodmind commented 6 years ago

so, for example, if we have component like styled('div')({color: 'red'}), we'll have just one classname for all instances. on the other hand, if we have component like styled('div')({color: 'red'}), we'll generate classname for each rendered component because of dynamic value.

I think there's should be props.color?

lttb commented 6 years ago

I think there's should be props.color?

right, it's a typo

lttb commented 6 years ago

oh, I'm sorry forgot another one approach like this :) but I'd prefer styled-components way

const styled = Styled({
  message: {
      '&:not(:first-child) $authorName': {
        display: 'none'
      },
      '&:not(:last-child) $styledPeerPhoto': {
        visibility: 'hidden'
      }
  },
  authorName: {},
  styledPeerPhoto: {}
})

const Message = styled('div')({composes: '$message'})

export default injectStyled(styled)(({classes}) => (
  <Message>
    <AuthorName className={classes.authorName}>author</AuthorName>
    <Avatar
      className={classes.styledPeerPhoto} 
      src="https://avatars2.githubusercontent.com/u/11135392?v=4&s=88"
    />
  </Message>
))

https://www.webpackbin.com/bins/-KrDXJZWZgM6d3ovH7PA

lttb commented 6 years ago

Hi @goodmind,

We've finally released this feature!

You can check your example here https://www.webpackbin.com/bins/-KwJAMdFdN8myP7g6dpD