a-tonchev

a-tonchev

Member Since 2 years ago

Experience Points
2
follower
Lessons Completed
3
follow
Lessons Completed
9
stars
Best Reply Awards
12
repos

78 contributions in the last year

Pinned
⚡ Basic Boilerplate for react - everything you need
⚡ Mobile-friendly Carousel 🎠 with batteries included (supporting touch, mouse emulation, lazy loading, thumbnails, fullscreen, RTL, keyboard navigation and customisations).
⚡ Boilerplate for Rest API with authentication, based on KOA and mongodb driver with JSON Schema validation (which is native for mongo)
⚡ A responsive image zoom component designed for shopping sites.
Activity
Jan
19
5 days ago
Activity icon
created branch
createdAt 5 days ago
Activity icon
issue

a-tonchev issue unlayer/react-email-editor

a-tonchev
a-tonchev

How to integrate the image picker like

Hello,

I would like to use the picker of free images similar like here:

image

Can we use somehow this component, or is this custom component that is not available in react-email-editor?

It would be nice if you give more information how you build this component and how to use the free images from pixabay/unsplash etc.. :)

Thanks

Dec
20
1 month ago
Dec
17
1 month ago
Activity icon
issue

a-tonchev issue GoogleChrome/lighthouse

a-tonchev
a-tonchev

Lighthouse is auditing without finishing in Chrome Devtools

FAQ

URL

https://demo2.shopsuy.com/

What happened?

Lighthouse is auditing but never finishes, it just stay at one position. PageSpeed Insights seems to work and delivers report, but the browser does not deliver any report.

What did you expect?

Lighthouse to show audit report

What have you tried?

I tried auditing using different laptops and PCs

How were you running Lighthouse?

Chrome DevTools

Lighthouse Version

latest of chrome 96.0.4664.110

Chrome Version

Version 96.0.4664.110 (Official Build) (64-bit)

Node Version

No response

OS

Windows 10

Relevant log output

No response

Dec
10
1 month ago
Activity icon
issue

a-tonchev issue comment yifaneye/react-gallery-carousel

a-tonchev
a-tonchev

Allow zoom in in mobile double tab

Right now if I double tap image in full screen mode it has zoom in effect, but it zooms also arrows and the whole window. After exiting zoom I can not slide any more until I click again on the arrow, after that everything starts to work normal.

It would be nice to have double-tap and 2 finger stretch zoom similar like amazon when open on mobile view:

https://www.amazon.de/gp/aw/d/B01C37CRZS/?encoding=UTF8&pd_rd_plhdr=t&aaxitk=d0cbebe4194d6edc5093cd9cda6b705d&hsa_cr_id=5069197050902&ref=sbx_be_s_sparkle_scm_asin_0_img&pd_rd_w=SpWBU&pf_rd_p=93aef975-2fed-4353-91a2-d32b278d7c02&pd_rd_wg=rBmS8&pf_rd_r=5RZJMMX3CJ35EZN88GSC&pd_rd_r=2787af93-7ff4-4207-9d1a-187bd98b598f#immersive-view_1624784083156

a-tonchev
a-tonchev

@yifaneye you can open full screen mode and try to zoom in and out with 2 fingers. After that try to slide with the finger again (not with the arrow) I get this issue on all devices home :) Iphone 4, Pocophone f1, Samsung Galaxy Tab s7+

Nov
30
1 month ago
Activity icon
issue

a-tonchev issue nextapps-de/flexsearch

a-tonchev
a-tonchev

logic operators are not working

Somehow it does not matter if I use the

    const searchQueries = [{
      field: 'productDescription',
      query: '17',
      bool: 'and',
    }, {
      field: 'ean',
      query: '17',
      bool: 'and',
    }];

or

    const searchQueries = {
      field: ['productDescription', 'ean'],
      query: '17',
      bool: 'and',
    };

It always show all possible documents where any of both fields has 17 in it.

Activity icon
issue

a-tonchev issue comment nextapps-de/flexsearch

a-tonchev
a-tonchev

Multi-fields search in documents is not working

Hi,

Following the doc this sample code should work but it yields an empty array. Any clues about what is done wrong?

var { Document } = require(`flexsearch`);

var index = new Document({
  document: {
    id: "id",
    index: ["title"]
  }
});

index.add({
  id: 0,
  title: "I am a test"
});
index.add({
  id: 1,
  title: "I am also a test"
});

var result = index.search([
  {
    field: "title",
    query: "test"
  },
  {
    field: "title",
    query: "also"
  }
]);
console.log(`result`, JSON.stringify(result));
a-tonchev
a-tonchev

I also face this bug, what would be the workaround?

Nov
26
1 month ago
push

a-tonchev push a-tonchev/react-boilerplate

a-tonchev
a-tonchev

replace recoil callback with recoil value

commit sha: cee0f58213e3aaeb924d313de44567b88ccac2a7

push time in 1 month ago
Nov
23
2 months ago
push

a-tonchev push a-tonchev/react-boilerplate

a-tonchev
a-tonchev

Remove Import React Replace classes

commit sha: a5df736f7d2fad3bf1558469d4e531eb377473d9

push time in 2 months ago
Activity icon
issue

a-tonchev issue comment vitejs/vite

a-tonchev
a-tonchev

Scripts set in manualChunks are loaded directly in front page, instead to be lazy loaded when needed

Describe the bug

To manage well the bundle, I am setting the packages into manualChunks e.g.:

The package fabric is used only in the admin area of my app, that is why I don't need it to be loaded directly in the front page.

If I don't set it in manualChunks, it works good and it will not be loaded in the front page, but my chunks then are too large, because vite place it automatically together with others in a huge backend chunk. Then as soon I open the backend it lazy loads all the other chunks, including the one that contains fabric. So this is the expected behavior.

If I set it in manualChunks, e.g.:

    rollupOptions: {
      output: {
        manualChunks: {
          fabric: ['fabric'],
        }
     }
   }

the fabric chunk is loaded directly on the front page. Even if I am not admin.

You can see the differences when I include fabric or not:

Not included in manualChunks image

Included in manualChunks: image

Expected behavior is: fabric should only be loaded when really used, else it creates only network traffic and lowers the Lighthouse score because of unused code!

NOTE: I am using an example with fabric here, but in my project I have a bunch of other libraries that have the same issue with manualChunks.

Reproduction

I created a small reproduction in this repo:

https://github.com/a-tonchev/react-boilerplate/tree/vite_no_lazy_load

Steps to reproduce:

  1. Install deps (yarn)

Try bug:

  1. yarn build && yarn serve
  2. Open localhost:4000 and see in Network -> JS, the fabric script is loaded

To try without, open vite.config.js: https://github.com/a-tonchev/react-boilerplate/blob/vite_no_lazy_load/vite.config.js

and comment out line 40

  1. yarn build && yarn serve
  2. Open localhost:4000 and see in Network -> JS, the fabric script is no more loaded,

System Info

Windows 10 + WSL (Ubuntu)

Vite version "^2.3.8"

Used Package Manager

yarn

Logs

No response

Validations

a-tonchev
a-tonchev

On the other hand, it is good to have the option to decide which chunks should be loaded immediately, because thus we will avoid the waterfall-effect on chunks that are always needed.

I suggest to have either two rules manualChunks + preloadChunks or just to put this option in the manualChunks e.g. { chunkUrl, preload: true }

Nov
22
2 months ago
push

a-tonchev push a-tonchev/react-boilerplate

a-tonchev
a-tonchev

Remove Import React Replace classes

commit sha: 87b165db53084d9c139a435b57205bb5e07bb578

push time in 2 months ago
Nov
20
2 months ago
Activity icon
issue

a-tonchev issue nextapps-de/flexsearch

a-tonchev
a-tonchev

Add boost per field

It would be nice to have boosted field:

For example if I have { category, title, description ...}

I search for "laptop", the category field would be the highest scoring, then the title would have less score than field category but higher than description etc.

Activity icon
issue

a-tonchev issue comment nextapps-de/flexsearch

a-tonchev
a-tonchev

fuzzy search and typos

Is there any way to support typos/misspellings of a word? Like a hamilton distance search where anything with a small distance is also included? eg: if I misspell tetx instead text. Is this supported?

a-tonchev
a-tonchev

I also need this feature. In other libraries you could provide e.g. fuzzyness: 0.2

Nov
19
2 months ago
Activity icon
issue

a-tonchev issue mui-org/material-ui

a-tonchev
a-tonchev

Adding inputProps to a TextField inside Autocomplete cause crash

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

Screen crash with error message:

**TypeError Cannot read properties of null (reading 'removeAttribute')

MUI: Unable to find the input element. It was resolved to null while an HTMLInputElement was expected.**

Expected behavior 🤔

Should not Crash

Steps to reproduce 🕹

Crashing Demo:

https://codesandbox.io/s/checkboxestags-material-demo-forked-ft3mx?file=/demo.js

Context 🔦

No response

Your environment 🌎

No response

Nov
9
2 months ago
Activity icon
issue

a-tonchev issue comment nfl/react-helmet

a-tonchev
a-tonchev

How do I know the scripts are ready?

I use Helmet to load scripts like firebase library. Is there an event handler that tells me when the scripts are loaded and ready? Now I can't access my library since I use it inside componentDidMount but the library is downloaded asynchronously after render Helmet

a-tonchev
a-tonchev

My solution is like this:

const onLoadFunction = () => { console.log('helmet loaded'); }

window.onHelmetLoad = onLoadFunction;

useEffect(() => {
  return () => {
    window.onHelmetLoad = null;
  }
}, []);


<Helmet>
        <title>Some Title</title>
        <meta property="og:image" content={ogImage} />
        <meta property="og:title" content={ogTitle} />
        <script>window.onHelmetLoad()</script>
</Helmet>

Notes:

  • window.onHelmetLoad is placed as string and not a function in the Helmet childrens
  • I use useEffect to cleanup the window.onHelmetLoad when the component is unmounted, as a good practice, and not to have collision with some other place I am going to use the same approach.
Nov
8
2 months ago
Activity icon
issue

a-tonchev issue comment mui-org/material-ui

a-tonchev
a-tonchev

[RFC] v5 styling solution 💅

This RFC is a proposal for changing the styling solution of Material-UI in v5.

TL:DR; the core team proposes we go with emotion

What's the problem?

  • Maintaining & developing a great styling engine takes a considerable amount of time. We have experienced it first hand. Over the last 12 months, we have preferred to invest time on our core value proposition: the UI components, rather than improve the style engine. Working on it has a high opportunity cost.
  • We have been facing issues with supporting dynamic styles for the components. The performance of our custom dynamic styles implementation (based on props) isn't great (see the performance benchmarks below). This is seriously limiting the quality of the Developer Experience we can provide. It's a blocker for improving our API around customizability or ease of writing styles. For instance, it will unlock: style utils props, color variant, and custom variant.
  • The React community, at large, hasn't voted for using JSS at scale (JSS is great and still used). 3 years ago we bet on the best option available. We have to recognize better options are available now. We can move faster and unlock better DX/UX by building on top of a more popular, existing, styling solution.
  • Many developers use styled-components to override Material-UI's styles. End-users find themselves with two CSS-in-JS libraries in their bundle. Not great. It would be better if we could offer different adapters for different CSS-in-JS libraries. (Potential problems: we may need to re-write the core styles to match the syntax of the engine used 🤷‍♀️)

What are the requirements?

Whatever styling engine we choose to go with we have to consider the following factors:

  • performance: the faster the better but we are willing to trade some performance to improve the DX.
  • bundle size: below our current 14.3 kB gzipped would be great.
  • support concurrent mode: @material-ui/styles has partial support as I'm writing.
  • support SSR
  • simple customization
  • allow dynamic styling
  • good community size
  • theming
  • flat specificity
  • RTL
  • TypeScript

It would be nice if it can support the following:

What are our options?

  • styled-components
  • emotion
  • JSS (currently wrapped in material-ui)
  • styletron
  • Aphrodite
  • fela
  • else?

Comparison

Performance

Here are benchmarks with dynamic styles of several popular libraries (note the Material-UI v4 only use static styles which have good performance):

PR for reference: https://github.com/mnajdova/react-native-web/pull/1

Based on the performance, I think that we should eliminate: JSS (currently wrapped in @material-ui/styles), styletron, and fela. That would leave us with:

  • styled-components
  • emotion
  • Aphrodite
  • JSS
  • react-styletron
  • fela

Dynamic props

Based on the open issues, it seems that Aphrodite doesn't support dynamic props: https://github.com/Khan/aphrodite/issues/141 which in my opinion means that we should drop that one from our options too, leaving us with:

  • styled-components
  • emotion
  • Aphrodite
  • react-styletron

npm

While styled-components and emotion are both libraries are pretty popular, react-styletron at the time or writing is much behind with around 12500 downloads per week (this in my opinion is a strong reason why we should eliminate it, as if we decide to go with it, the community will again need to have two different styling engine in their apps).

Here is the list rang by the number of Weekly downloads at the time of writing:

Note that storybook has a dependency on emotion. It significantly skews the stats.

  • styled-components
  • emotion
  • react-styletron

Support concurrent mode

  • emotion: YES. Since v10 it is strict mode compatible based on their announcement post. I have tested it on a simple project that works as expected.
  • styled-components: Partial. There is at least one bug with global styles in strict mode.

SSR

Stars

  • styled-components: 30.6k
  • emotion: 11.4k
  • JSS: 5.9k

Trafic on the documentation

SimilarWeb estimated sessions/month:

  • sass-lang.com: ~476K/month (for comparison)
  • styled-components.com: ~239K/month
  • emotion.sh: ~59K/month
  • cssinjs.org: <30k/month (for comparison)

Users feedback

Based on the survey, 53.8% percent are using the Material-UI styles (JSS), which is not a surprise as it is the engine coming from Material-UI. However, we can see that 20.4% percent are already using styled-components, which is a big number considering that we don't have direct support for it. Emotion is used by around 1.9% percent of the developers currently based on the survey.

Having these numbers we want to push with better support for styled-components, so this is something we should consider.

Browser support

  • emotion: modern evergreen browsers + IE11
  • styled-components: not documented for v5, but the previous versions support the following

Bundle size

What's the best option?

Default engine

Even if we decide to support multiple engines, we would still need to advocate for one by default and have one documented in the demos.

styled-components

Pros:

  • Has the biggest community, people love to use it.
  • Performance starting from v5 is good.

Cons:

  • It will mean that all components styles need to be created using the styled API, which means for developers they will always have wrapper components if they need to re-style.
  • Lack of full concurrent support, which may create blockers down the road.

emotion

Pros:

  • Relatively large community, growing.
  • Good performance.
  • Concurrent mode + SSR would be possible out of the box.
  • The CSS prop can be useful for overrides.
  • Source map support.
  • A bit smaller.

Cons:

Support multiple

We may try to support multiple CSS-in-JS solutions, by providing our in house adapters for them. Some things that we need to consider is that, that we may have duplicate work on the styles, as the syntax is different between them (at least jss compared to styled-components/emotion). We will reuse the theme object no matter what solution we will pick up.

The less involved support for this may come from the usage of the styled, as people may do some webpack config to decide which one to use - (this is just something to consider).

Additional comments

Deterministic classnames on the components that can be targeted for custom styles

Regarding how the classes look and how developers may target them, I want to show a comparison of what we currently have and how the problem can be solved with the new approach.

As an example, I will take the Slider component. Here is currently how the generated DOM look like:

Each of the classes has a very well descriptive semantic and people can use these classes for overriding the styles of the component.

On the other hand, emotion, styled-components or any other similar library will create some hash as a class name. For us to solve this and offer the developers the same functionality for targeting classes, each of the components will add classes that can be targeted by the developers based on the props.

This would mean that apart from the classes generated by emotion, each component will still have the classes that we had previously, like MuiSlider-root & MuiSlider-colorPrimary, the only difference would be that this classes will now be used purely as selectors, rather than defining the styles for the components. This could be implemented like a hook - useSliderClasses

Conclusion

No matter which solution we would choose, we would use the styled API, which is supported by the two of them. This will allow us down the road to have easier support for styled + unstyled components (probably with webpack aliases, like for using preact).

After we investigated the two options we had in the end, the core team proposes we go with emotion. Some key elements:

A small migration cost between styled-components and emotion

Developers already using styled-components should be able to use emotion with almost no effort.

There are different ways for adding overrides other than wrapper components

The support of cx + css from emotion can be beneficial for developers to use it as an alternative for adding style overrides if they don't want to create wrapper components.

Concurrent mode is for sure supported :+1:

Kudos to @ryancogswell for doing a deeper investigation on this topic. So far we did not find anything in @emotion's code that would give us concern that concurrent mode wouldn't work. We were also looking into createGlobalStyle from styled-components as a comparison to emotion's Global component. It is doing most of its work during render (inherently problematic for Strict/Concurrent Mode) and just using useEffect for removing styles in its cleanup function. createGlobalStyle needs a complete rewrite before it will be usable in concurrent mode -- it isn't OK for it to add styles during render if that render is never committed. It looks like someone has tried rewriting it with some further changes in the last month, so we will need to follow this progress.

How is the specificity handled

Emotion's docs recommend doing composition of CSS into a single class rather than trying to leverage styles from multiple class names. In v5, our existing global class names would be applied without any styles attached to them. The composition of emotion-styled components automatically combines the styles into a single class. This potentially gets rid of these stylesheet order issues at least internal to the styles defined by Material-UI, because every component's styles are driven by a single class name :+1:. So we would have the global class names (for developers to target in various ways for customizations) and then a single generated (by emotion) class name per element that would consolidate all the CSS sources flowing into it. Specificity is then handled by emotion based on the order of composition. All compositions using emotion (whether render-time or definition-time composition) results in a single class on the element. styled-components does NOT work this way concerning render-time composition (definition-time composition does get combined into a single class). The same composition in styled-components results in multiple classes applied to the same element and the specificity does not work as I would have intended.

Alternatives


What do you think about it?

Activity icon
issue

a-tonchev issue comment mui-org/material-ui

a-tonchev
a-tonchev

[RFC] v5 styling solution 💅

This RFC is a proposal for changing the styling solution of Material-UI in v5.

TL:DR; the core team proposes we go with emotion

What's the problem?

  • Maintaining & developing a great styling engine takes a considerable amount of time. We have experienced it first hand. Over the last 12 months, we have preferred to invest time on our core value proposition: the UI components, rather than improve the style engine. Working on it has a high opportunity cost.
  • We have been facing issues with supporting dynamic styles for the components. The performance of our custom dynamic styles implementation (based on props) isn't great (see the performance benchmarks below). This is seriously limiting the quality of the Developer Experience we can provide. It's a blocker for improving our API around customizability or ease of writing styles. For instance, it will unlock: style utils props, color variant, and custom variant.
  • The React community, at large, hasn't voted for using JSS at scale (JSS is great and still used). 3 years ago we bet on the best option available. We have to recognize better options are available now. We can move faster and unlock better DX/UX by building on top of a more popular, existing, styling solution.
  • Many developers use styled-components to override Material-UI's styles. End-users find themselves with two CSS-in-JS libraries in their bundle. Not great. It would be better if we could offer different adapters for different CSS-in-JS libraries. (Potential problems: we may need to re-write the core styles to match the syntax of the engine used 🤷‍♀️)

What are the requirements?

Whatever styling engine we choose to go with we have to consider the following factors:

  • performance: the faster the better but we are willing to trade some performance to improve the DX.
  • bundle size: below our current 14.3 kB gzipped would be great.
  • support concurrent mode: @material-ui/styles has partial support as I'm writing.
  • support SSR
  • simple customization
  • allow dynamic styling
  • good community size
  • theming
  • flat specificity
  • RTL
  • TypeScript

It would be nice if it can support the following:

What are our options?

  • styled-components
  • emotion
  • JSS (currently wrapped in material-ui)
  • styletron
  • Aphrodite
  • fela
  • else?

Comparison

Performance

Here are benchmarks with dynamic styles of several popular libraries (note the Material-UI v4 only use static styles which have good performance):

PR for reference: https://github.com/mnajdova/react-native-web/pull/1

Based on the performance, I think that we should eliminate: JSS (currently wrapped in @material-ui/styles), styletron, and fela. That would leave us with:

  • styled-components
  • emotion
  • Aphrodite
  • JSS
  • react-styletron
  • fela

Dynamic props

Based on the open issues, it seems that Aphrodite doesn't support dynamic props: https://github.com/Khan/aphrodite/issues/141 which in my opinion means that we should drop that one from our options too, leaving us with:

  • styled-components
  • emotion
  • Aphrodite
  • react-styletron

npm

While styled-components and emotion are both libraries are pretty popular, react-styletron at the time or writing is much behind with around 12500 downloads per week (this in my opinion is a strong reason why we should eliminate it, as if we decide to go with it, the community will again need to have two different styling engine in their apps).

Here is the list rang by the number of Weekly downloads at the time of writing:

Note that storybook has a dependency on emotion. It significantly skews the stats.

  • styled-components
  • emotion
  • react-styletron

Support concurrent mode

  • emotion: YES. Since v10 it is strict mode compatible based on their announcement post. I have tested it on a simple project that works as expected.
  • styled-components: Partial. There is at least one bug with global styles in strict mode.

SSR

Stars

  • styled-components: 30.6k
  • emotion: 11.4k
  • JSS: 5.9k

Trafic on the documentation

SimilarWeb estimated sessions/month:

  • sass-lang.com: ~476K/month (for comparison)
  • styled-components.com: ~239K/month
  • emotion.sh: ~59K/month
  • cssinjs.org: <30k/month (for comparison)

Users feedback

Based on the survey, 53.8% percent are using the Material-UI styles (JSS), which is not a surprise as it is the engine coming from Material-UI. However, we can see that 20.4% percent are already using styled-components, which is a big number considering that we don't have direct support for it. Emotion is used by around 1.9% percent of the developers currently based on the survey.

Having these numbers we want to push with better support for styled-components, so this is something we should consider.

Browser support

  • emotion: modern evergreen browsers + IE11
  • styled-components: not documented for v5, but the previous versions support the following

Bundle size

What's the best option?

Default engine

Even if we decide to support multiple engines, we would still need to advocate for one by default and have one documented in the demos.

styled-components

Pros:

  • Has the biggest community, people love to use it.
  • Performance starting from v5 is good.

Cons:

  • It will mean that all components styles need to be created using the styled API, which means for developers they will always have wrapper components if they need to re-style.
  • Lack of full concurrent support, which may create blockers down the road.

emotion

Pros:

  • Relatively large community, growing.
  • Good performance.
  • Concurrent mode + SSR would be possible out of the box.
  • The CSS prop can be useful for overrides.
  • Source map support.
  • A bit smaller.

Cons:

Support multiple

We may try to support multiple CSS-in-JS solutions, by providing our in house adapters for them. Some things that we need to consider is that, that we may have duplicate work on the styles, as the syntax is different between them (at least jss compared to styled-components/emotion). We will reuse the theme object no matter what solution we will pick up.

The less involved support for this may come from the usage of the styled, as people may do some webpack config to decide which one to use - (this is just something to consider).

Additional comments

Deterministic classnames on the components that can be targeted for custom styles

Regarding how the classes look and how developers may target them, I want to show a comparison of what we currently have and how the problem can be solved with the new approach.

As an example, I will take the Slider component. Here is currently how the generated DOM look like:

Each of the classes has a very well descriptive semantic and people can use these classes for overriding the styles of the component.

On the other hand, emotion, styled-components or any other similar library will create some hash as a class name. For us to solve this and offer the developers the same functionality for targeting classes, each of the components will add classes that can be targeted by the developers based on the props.

This would mean that apart from the classes generated by emotion, each component will still have the classes that we had previously, like MuiSlider-root & MuiSlider-colorPrimary, the only difference would be that this classes will now be used purely as selectors, rather than defining the styles for the components. This could be implemented like a hook - useSliderClasses

Conclusion

No matter which solution we would choose, we would use the styled API, which is supported by the two of them. This will allow us down the road to have easier support for styled + unstyled components (probably with webpack aliases, like for using preact).

After we investigated the two options we had in the end, the core team proposes we go with emotion. Some key elements:

A small migration cost between styled-components and emotion

Developers already using styled-components should be able to use emotion with almost no effort.

There are different ways for adding overrides other than wrapper components

The support of cx + css from emotion can be beneficial for developers to use it as an alternative for adding style overrides if they don't want to create wrapper components.

Concurrent mode is for sure supported :+1:

Kudos to @ryancogswell for doing a deeper investigation on this topic. So far we did not find anything in @emotion's code that would give us concern that concurrent mode wouldn't work. We were also looking into createGlobalStyle from styled-components as a comparison to emotion's Global component. It is doing most of its work during render (inherently problematic for Strict/Concurrent Mode) and just using useEffect for removing styles in its cleanup function. createGlobalStyle needs a complete rewrite before it will be usable in concurrent mode -- it isn't OK for it to add styles during render if that render is never committed. It looks like someone has tried rewriting it with some further changes in the last month, so we will need to follow this progress.

How is the specificity handled

Emotion's docs recommend doing composition of CSS into a single class rather than trying to leverage styles from multiple class names. In v5, our existing global class names would be applied without any styles attached to them. The composition of emotion-styled components automatically combines the styles into a single class. This potentially gets rid of these stylesheet order issues at least internal to the styles defined by Material-UI, because every component's styles are driven by a single class name :+1:. So we would have the global class names (for developers to target in various ways for customizations) and then a single generated (by emotion) class name per element that would consolidate all the CSS sources flowing into it. Specificity is then handled by emotion based on the order of composition. All compositions using emotion (whether render-time or definition-time composition) results in a single class on the element. styled-components does NOT work this way concerning render-time composition (definition-time composition does get combined into a single class). The same composition in styled-components results in multiple classes applied to the same element and the specificity does not work as I would have intended.

Alternatives


What do you think about it?

a-tonchev
a-tonchev

@EloB If you want to optimize the styles more, you could try to use global css variables:

import { css } from '@emotion/react';
import { useTheme } from '@mui/material';

const GlobalStyles = () => {
  const theme = useTheme();

  const styles = useMemo(() => css({
    ':root': {
      '--theme-breakpoints-values-sm': `${theme.breakpoints.values.sm}px`,
      '--theme-spacing-1': theme.spacing(1),
      '--theme-spacing-2': theme.spacing(2),
      '--theme-spacing-3_0_2': theme.spacing(3, 0, 2),
      '--theme-spacing-0_1': theme.spacing(0, 1),
      '--theme-spacing-8': theme.spacing(8),
      '--theme-palette-primary-main': theme.palette.primary.main,
      '--theme-palette-success-main': theme.palette.success.main,
      '--theme-palette-warning-main': theme.palette.warning.main,
      '--theme-palette-secondary-main': theme.palette.secondary.main,
      '--theme-palette-success-contrastText': theme.palette.success.contrastText,
      '--theme-palette-primary-contrastText': theme.palette.primary.contrastText,
      '--theme-palette-error-contrastText': theme.palette.error.contrastText,
      '--theme-palette-error-main': theme.palette.error.main,
    },
  }), [theme]);

  return <Global styles={styles} />;
};

And put this element inside some top-level component.

Then you can use everywhere the styles like this:

const mySxValues = {
  backgroundColor: 'var(--theme-palette-secondary-main)',
};

Or in styles:

const styles = {
  someClass: {
    backgroundColor: 'var(--theme-palette-secondary-main)',
  },
};

Thus you don't need to generate dynamically the theme object for your styles and you get better performance. Beside that you can use pure css using dynamically the values from your material themeprovider.

Activity icon
issue

a-tonchev issue comment mui-org/material-ui

a-tonchev
a-tonchev

[RFC] v5 styling solution 💅

This RFC is a proposal for changing the styling solution of Material-UI in v5.

TL:DR; the core team proposes we go with emotion

What's the problem?

  • Maintaining & developing a great styling engine takes a considerable amount of time. We have experienced it first hand. Over the last 12 months, we have preferred to invest time on our core value proposition: the UI components, rather than improve the style engine. Working on it has a high opportunity cost.
  • We have been facing issues with supporting dynamic styles for the components. The performance of our custom dynamic styles implementation (based on props) isn't great (see the performance benchmarks below). This is seriously limiting the quality of the Developer Experience we can provide. It's a blocker for improving our API around customizability or ease of writing styles. For instance, it will unlock: style utils props, color variant, and custom variant.
  • The React community, at large, hasn't voted for using JSS at scale (JSS is great and still used). 3 years ago we bet on the best option available. We have to recognize better options are available now. We can move faster and unlock better DX/UX by building on top of a more popular, existing, styling solution.
  • Many developers use styled-components to override Material-UI's styles. End-users find themselves with two CSS-in-JS libraries in their bundle. Not great. It would be better if we could offer different adapters for different CSS-in-JS libraries. (Potential problems: we may need to re-write the core styles to match the syntax of the engine used 🤷‍♀️)

What are the requirements?

Whatever styling engine we choose to go with we have to consider the following factors:

  • performance: the faster the better but we are willing to trade some performance to improve the DX.
  • bundle size: below our current 14.3 kB gzipped would be great.
  • support concurrent mode: @material-ui/styles has partial support as I'm writing.
  • support SSR
  • simple customization
  • allow dynamic styling
  • good community size
  • theming
  • flat specificity
  • RTL
  • TypeScript

It would be nice if it can support the following:

What are our options?

  • styled-components
  • emotion
  • JSS (currently wrapped in material-ui)
  • styletron
  • Aphrodite
  • fela
  • else?

Comparison

Performance

Here are benchmarks with dynamic styles of several popular libraries (note the Material-UI v4 only use static styles which have good performance):

PR for reference: https://github.com/mnajdova/react-native-web/pull/1

Based on the performance, I think that we should eliminate: JSS (currently wrapped in @material-ui/styles), styletron, and fela. That would leave us with:

  • styled-components
  • emotion
  • Aphrodite
  • JSS
  • react-styletron
  • fela

Dynamic props

Based on the open issues, it seems that Aphrodite doesn't support dynamic props: https://github.com/Khan/aphrodite/issues/141 which in my opinion means that we should drop that one from our options too, leaving us with:

  • styled-components
  • emotion
  • Aphrodite
  • react-styletron

npm

While styled-components and emotion are both libraries are pretty popular, react-styletron at the time or writing is much behind with around 12500 downloads per week (this in my opinion is a strong reason why we should eliminate it, as if we decide to go with it, the community will again need to have two different styling engine in their apps).

Here is the list rang by the number of Weekly downloads at the time of writing:

Note that storybook has a dependency on emotion. It significantly skews the stats.

  • styled-components
  • emotion
  • react-styletron

Support concurrent mode

  • emotion: YES. Since v10 it is strict mode compatible based on their announcement post. I have tested it on a simple project that works as expected.
  • styled-components: Partial. There is at least one bug with global styles in strict mode.

SSR

Stars

  • styled-components: 30.6k
  • emotion: 11.4k
  • JSS: 5.9k

Trafic on the documentation

SimilarWeb estimated sessions/month:

  • sass-lang.com: ~476K/month (for comparison)
  • styled-components.com: ~239K/month
  • emotion.sh: ~59K/month
  • cssinjs.org: <30k/month (for comparison)

Users feedback

Based on the survey, 53.8% percent are using the Material-UI styles (JSS), which is not a surprise as it is the engine coming from Material-UI. However, we can see that 20.4% percent are already using styled-components, which is a big number considering that we don't have direct support for it. Emotion is used by around 1.9% percent of the developers currently based on the survey.

Having these numbers we want to push with better support for styled-components, so this is something we should consider.

Browser support

  • emotion: modern evergreen browsers + IE11
  • styled-components: not documented for v5, but the previous versions support the following

Bundle size

What's the best option?

Default engine

Even if we decide to support multiple engines, we would still need to advocate for one by default and have one documented in the demos.

styled-components

Pros:

  • Has the biggest community, people love to use it.
  • Performance starting from v5 is good.

Cons:

  • It will mean that all components styles need to be created using the styled API, which means for developers they will always have wrapper components if they need to re-style.
  • Lack of full concurrent support, which may create blockers down the road.

emotion

Pros:

  • Relatively large community, growing.
  • Good performance.
  • Concurrent mode + SSR would be possible out of the box.
  • The CSS prop can be useful for overrides.
  • Source map support.
  • A bit smaller.

Cons:

Support multiple

We may try to support multiple CSS-in-JS solutions, by providing our in house adapters for them. Some things that we need to consider is that, that we may have duplicate work on the styles, as the syntax is different between them (at least jss compared to styled-components/emotion). We will reuse the theme object no matter what solution we will pick up.

The less involved support for this may come from the usage of the styled, as people may do some webpack config to decide which one to use - (this is just something to consider).

Additional comments

Deterministic classnames on the components that can be targeted for custom styles

Regarding how the classes look and how developers may target them, I want to show a comparison of what we currently have and how the problem can be solved with the new approach.

As an example, I will take the Slider component. Here is currently how the generated DOM look like:

Each of the classes has a very well descriptive semantic and people can use these classes for overriding the styles of the component.

On the other hand, emotion, styled-components or any other similar library will create some hash as a class name. For us to solve this and offer the developers the same functionality for targeting classes, each of the components will add classes that can be targeted by the developers based on the props.

This would mean that apart from the classes generated by emotion, each component will still have the classes that we had previously, like MuiSlider-root & MuiSlider-colorPrimary, the only difference would be that this classes will now be used purely as selectors, rather than defining the styles for the components. This could be implemented like a hook - useSliderClasses

Conclusion

No matter which solution we would choose, we would use the styled API, which is supported by the two of them. This will allow us down the road to have easier support for styled + unstyled components (probably with webpack aliases, like for using preact).

After we investigated the two options we had in the end, the core team proposes we go with emotion. Some key elements:

A small migration cost between styled-components and emotion

Developers already using styled-components should be able to use emotion with almost no effort.

There are different ways for adding overrides other than wrapper components

The support of cx + css from emotion can be beneficial for developers to use it as an alternative for adding style overrides if they don't want to create wrapper components.

Concurrent mode is for sure supported :+1:

Kudos to @ryancogswell for doing a deeper investigation on this topic. So far we did not find anything in @emotion's code that would give us concern that concurrent mode wouldn't work. We were also looking into createGlobalStyle from styled-components as a comparison to emotion's Global component. It is doing most of its work during render (inherently problematic for Strict/Concurrent Mode) and just using useEffect for removing styles in its cleanup function. createGlobalStyle needs a complete rewrite before it will be usable in concurrent mode -- it isn't OK for it to add styles during render if that render is never committed. It looks like someone has tried rewriting it with some further changes in the last month, so we will need to follow this progress.

How is the specificity handled

Emotion's docs recommend doing composition of CSS into a single class rather than trying to leverage styles from multiple class names. In v5, our existing global class names would be applied without any styles attached to them. The composition of emotion-styled components automatically combines the styles into a single class. This potentially gets rid of these stylesheet order issues at least internal to the styles defined by Material-UI, because every component's styles are driven by a single class name :+1:. So we would have the global class names (for developers to target in various ways for customizations) and then a single generated (by emotion) class name per element that would consolidate all the CSS sources flowing into it. Specificity is then handled by emotion based on the order of composition. All compositions using emotion (whether render-time or definition-time composition) results in a single class on the element. styled-components does NOT work this way concerning render-time composition (definition-time composition does get combined into a single class). The same composition in styled-components results in multiple classes applied to the same element and the specificity does not work as I would have intended.

Alternatives


What do you think about it?

a-tonchev
a-tonchev

@EloB @garronej guys I think it would be not bad idea to make blog/articles in this direction. The topic is quite interesting!

Nov
4
2 months ago
Activity icon
issue

a-tonchev issue comment facebook/react

a-tonchev
a-tonchev

Bug: Rules with suggestions must set the `meta.hasSuggestions` property to `true`

I'm basically running into an issue where eslint is asking me to set meta.hasSuggestions to true. When I use "react-hooks/exhaustive-deps": "error". Is there something I'm doing wrong or is this a dep version thing?

React version:

Steps To Reproduce

  1. Have my eslint config:
{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 13,
    "sourceType": "module"
  },
  "plugins": ["react", "react-hooks", "@typescript-eslint"],
  "rules": {
    "react-hooks/exhaustive-deps": "error",
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}

Here's my deps from package.json

{
"dependecies": {
    "eslint": "^8.0.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-react": "^7.26.1",
    "eslint-plugin-react-hooks": "^4.2.0",
}

If I try to remove the react-hook plugin and extension this happens: Definition for rule 'react-hooks/exhaustive-deps' was not found

Link to code example:

The current behavior

The expected behavior

a-tonchev
a-tonchev

Running npm install [email protected] worked for me

This works for me, thanks!

Activity icon
issue

a-tonchev issue import-js/eslint-plugin-import

a-tonchev
a-tonchev

Import order of groups messed up

I have following eslint rules:

   "import/order": ["error", {
      "newlines-between": "always",
      "groups": [["builtin", "external"], "internal", ["index", "parent", "sibling"]],
      "pathGroups": [
        {
          "pattern": "@/",
          "group": "internal",
          "position": "after"
        }
      ]
    }]

This requires following order:

import ExternalPackage from 'somewhere';

import InternalPackage from '@/components/SomeLocalModule';

import Sibling from './SomeModule';

Until version 2.23.4 everything works fine. But after that the order of the sibling and the internal package "@components" is mixed up, the plugin requires me to switch the places of the Sibling and the @package.

Activity icon
issue

a-tonchev issue comment import-js/eslint-plugin-import

a-tonchev
a-tonchev

Import order of groups messed up

I have following eslint rules:

   "import/order": ["error", {
      "newlines-between": "always",
      "groups": [["builtin", "external"], "internal", ["index", "parent", "sibling"]],
      "pathGroups": [
        {
          "pattern": "@/",
          "group": "internal",
          "position": "after"
        }
      ]
    }]

This requires following order:

import ExternalPackage from 'somewhere';

import InternalPackage from '@/components/SomeLocalModule';

import Sibling from './SomeModule';

Until version 2.23.4 everything works fine. But after that the order of the sibling and the internal package "@components" is mixed up, the plugin requires me to switch the places of the Sibling and the @package.

a-tonchev
a-tonchev

I manage to solve this, aparently the pattern has been changed, so I needed to fix it like this:

From "pattern": "@/", to "pattern": "@/**",

It needs the two stars at the end to show that the pattern just starts with the symbols @/

Activity icon
issue

a-tonchev issue comment yifaneye/react-gallery-carousel

a-tonchev
a-tonchev

Allow zoom in in mobile double tab

Right now if I double tap image in full screen mode it has zoom in effect, but it zooms also arrows and the whole window. After exiting zoom I can not slide any more until I click again on the arrow, after that everything starts to work normal.

It would be nice to have double-tap and 2 finger stretch zoom similar like amazon when open on mobile view:

https://www.amazon.de/gp/aw/d/B01C37CRZS/?encoding=UTF8&pd_rd_plhdr=t&aaxitk=d0cbebe4194d6edc5093cd9cda6b705d&hsa_cr_id=5069197050902&ref=sbx_be_s_sparkle_scm_asin_0_img&pd_rd_w=SpWBU&pf_rd_p=93aef975-2fed-4353-91a2-d32b278d7c02&pd_rd_wg=rBmS8&pf_rd_r=5RZJMMX3CJ35EZN88GSC&pd_rd_r=2787af93-7ff4-4207-9d1a-187bd98b598f#immersive-view_1624784083156

a-tonchev
a-tonchev

@yifaneye maybe you can use something similar like https://manuelstofer.github.io/pinchzoom/

But I am not sure if pinchzoom is the best choice

Nov
2
2 months ago
Activity icon
created branch
createdAt 2 months ago
pull request

a-tonchev pull request a-tonchev/react-gallery-carousel

a-tonchev
a-tonchev

v0.2.5 (#59)

  • Allow users to pass a thumbnails array

  • Add an example for custom thumbnails

  • Add sizes to images

  • Add props, change images to responsive, and more relevant thumbnails

  • Add keys to list elements

  • v0.2.5

  • v0.2.5

Co-authored-by: Kostas Mouratidis [email protected]

Previous