Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS Panel #6

Open
streamich opened this issue Feb 6, 2018 · 4 comments
Open

CSS Panel #6

streamich opened this issue Feb 6, 2018 · 4 comments

Comments

@streamich
Copy link

streamich commented Feb 6, 2018

@krasimir Would you consider adding a panel that shows CSS devtools, more specifically CSS-in-JS devtools, I would be happy to write an adapter for freestyler.

  1. User can browse CSS-in-JS files
  2. There should be a way to link styles to React components — for example, when viewing styles user can click on React component they are attached to; and the other way around.
@krasimir
Copy link
Owner

krasimir commented Feb 6, 2018

That is absolutely possible. All we need to do is to write a CSS emitter. It's a script that runs on the page and fetches information about the CSS styles. Then construct an object (state) and send it to Kuker via window.postMessage. I just played a little bit and here is what happened:

screen shot 2018-02-06 at 9 21 58 pm

It's in this CodePen https://codepen.io/krasimir/pen/paErGV?editors=0010

The tricky parts in such emitter are:

  • Do we know when the CSS changes. If yes then this is half of the work. At this moment we have to call window.postMessage.
  • Can we easily construct a tree which represents the styles on the page. (that is the other half)

Here is some code:

function sendMessage(css) {
  window.postMessage({
    kuker: true,
    type: 'CSS_UPDATE',
    time: (new Date()).getTime(),
    state: css
  }, '*'); 
}
function extractCSS() {
  var css = {};
  for (let i = 0; i < document.styleSheets.length; i++) {
    var sheet = document.styleSheets[i];
    var rules = ('cssRules' in sheet) ? sheet.cssRules : sheet.rules;
    for (let j = 0; j<rules.length; j++) {
      let rule = rules[j];
      css[rule.selectorText] = Object.keys(rule.style).reduce((result, prop) => {
        if (rule.style[prop] !== '' && prop.toString().length >= 3) {
          result[prop] = rule.style[prop];
        }
        return result;
      }, {});
    }
  }
  
  return css;
}

const cssPlaceholder = document.querySelector('#js-driven-styles');

document.querySelector('button').addEventListener('click', function () {
  cssPlaceholder.innerHTML = `button { background: ${ getRandomColor() }; font-family: ${ getRandomFont() } }`;
  sendMessage(extractCSS());
});

sendMessage(extractCSS());

@streamich
Copy link
Author

streamich commented Feb 6, 2018

Nice! And its super simple to do with this postMessage() API as well. Few points below:

  1. What do you think about having a separate dedicated tab for CSS?
  2. In a real-world applications there will be hundreds of components on the site, if they each send the CSS_UPDATE event the even log will get flooded quickly.
  3. If the state does not change and I call CSS_UPDATE with the same state, what will kuker do?
  4. "Do we know when the CSS changes" - yes, every 4th+ generation CSS-in-JS library knows when it re-renders CSS.
  5. With regards to component tree, TBH, I'm not sure how to get it, but React's devtools does it somehow so it is possible. I guess it's done here.

@streamich
Copy link
Author

BTW, absurd.js site is down http://absurdjs.com/pages/installation/

@krasimir
Copy link
Owner

krasimir commented Feb 7, 2018

What do you think about having a separate dedicated tab for CSS?

I'm not quite sold on this idea. That is because Kuker is made to display events + state mutations. Should be agnostic what data those events hold and what the state tree represents.

In a real-world applications there will be hundreds of components on the site, if they each send the CSS_UPDATE event the even log will get flooded quickly.

That's true. That is why the emitter should implement some kind of throttling logic like React emitter does. Kuker itself works in requestAnimationFrame wrapper so it is capable of handling many events. The list inside the app uses virualization so handles nicely huge number of events.

If the state does not change and I call CSS_UPDATE with the same state, what will kuker do?

You'll get a new event on the left side panel and still the same state on the right side. Kuker tho gives you a hint which of the events are mutating the state.
kuker mutations

"Do we know when the CSS changes" - yes, every 4th+ generation CSS-in-JS library knows when it re-renders CSS.

That is nice but do those libraries has a hook where you may plug the postMessage call?

With regards to component tree, TBH, I'm not sure how to get it, but React's devtools does it somehow so it is possible. I guess it's done here.

Yep, it is possible and Kuker uses the same code (in a little bit hacky way) in the React emitter. Fetching the React component tree in real time requires lots of knowledge for how React works. I myself tried to do that alone and I failed. That's why Kuker uses code from React's devtools.
Mapping of components with CSS will be also really tricky because there are lots of CSS-in-JS solutions and they have some different ideas. What can be easily done is seeing the produced CSS and its mutations. Even the names of the produced CSS classes may be weird and unreadable.

BTW, absurd.js site is down http://absurdjs.com/pages/installation/

Yep, I decided to stop paying the domain and hosting and moved the site here http://absurdjs.krasimirtsonev.com/ Looking at the GA stats it had like ~10 hits per month so not really worth the money.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants