krasimir / kuker

Kick-ass browser extension to debug your apps
https://chrome.google.com/webstore/detail/glgnienmpgmfpkigngkmieconbnkmlcn
MIT License
657 stars 26 forks source link

CSS Panel #6

Open streamich opened 6 years ago

streamich commented 6 years ago

@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 commented 6 years ago

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:

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 commented 6 years ago

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 commented 6 years ago

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

krasimir commented 6 years ago

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.