Hacker News new | past | comments | ask | show | jobs | submit login
Evergreen: a React UI Framework built by Segment (segment.com)
593 points by ggregoire 5 months ago | hide | past | web | favorite | 296 comments




The question is: how many of these will be maintained several years later? Can you build a long term project on these?

Or the expectation is that one has to make a new UI anyway every several years to keep up with the changing fashion, so rewrites are inevitable?


I think rewriting UI systems every few years and reimplementing in various JS frameworks that come and go is a serious waste of manpower. I'd so wish people would embrace web components properly once and for all, with LitElement, Svelte or Stencil. This way we won't have to live with another framework-bootstrap clone again and again and everyone can contribute to one solution that will work with all JS frameworks.


If I had to guess, I would guess that React will still be around in 5 years, but I'm not sure web components will. Sure, they may still be a part of the standard, but they might be so obscure that there isn't enough of a community around them to be a feasible option. So I don't think using web-components is the silver bullet you imagine.

Also, I haven't seen a lot of companies saying "Well, Angular is working great for us, but React is hot and trendy so let's rewrite the current UI in it". Rather, I think UI framework switches happen for two reasons:

- They've accumulated so much technical debt with their existing solution that progress has slowed to a crawl, developer morale is really low, etc. A migration strategy can be found that doesn't have such an upfront cost, and will dramatically improve velocity as features are converted.

- The design is totally changing, or the product is being rethought, and so it's not an invisible code rewrite, it's essentially building a new product.

I think in both of these cases, it's a good use of developer time.


> If I had to guess, I would guess that React will still be around in 5 years, but I'm not sure web components will.

I agree, and this is why I use React (or rather Preact) for both apps and interactive elements on the page. The big caveat is that in practice it's really easy to end up with a React project that is much more difficult to maintain compared to a monolithic framework (Ember, Angular, Vue, even), because of all the other crap that might be used to take care of all the stuff React doesn't do.

For example, I recently took on a React project that used a whole bunch of other packages for state management, routing, etc., and a number of those packages were no longer supported (or outright compromised). While it's nice that React is still React, a lot of these other packages are tightly woven into the whole 'fabric' (react-swipeable-redux-router type stuff).

For my part, when I start a React project I try to minimize these problems by generally avoiding react-specific packages. So instead of react-router (which had its share of non-backwards-compatible updates), I'll just use page.js for routing. In some cases I might use the reactified version (Redux comes to mind, but I avoid that most of the time for smaller stuff).

This still isn't a panacea, and as a result I've been moving more and more stuff to a more 'vanilla' Railsy backend (Elixir/Phoenix, specifically). While the ecosystem does seem to be stabilizing a bit, it's still insane, and thankfully there are or will be ways to still add a bunch of 'dynamic' shit to the front-end without drowning in this insanity [1].

[1]: https://www.youtube.com/watch?v=Z2DU0qLfPIY


It seems replication of numerous UI frameworks to be a fruit of Evolution per se, and it will happen again and again.

You named Web Components, I've been embracing them for a while, but if you tried to switch from Google's Polymer to LitElement it wouldn't go smooth as you could have imagined. Both Polymer and LitElement are based on Shadow Dom and WC features curated by Google, but are not 100% backward compatible. That is to say, Web Components have been divided from within the same tech. No need to mention the rival concepts of "everything HTML" of Polymer 2.0 and fixing it to be "all JS and webpack-ready" in 3.0, and consequential deprecation of Bower.

And here you mention some Svelte and Stencil which I've never heard of before. Why need them? We have webcomponents.org already.


I think you confused multiple things together - why do you bring webcomponents.org the website into discussion, it has no relation here.

Web components are a low-level primitive - they are clunky to use directly.

Polymer and LitElement - are libraries - you can author WC's with them. And yes they are different (I used both), but you don't really have to migrate from one to another.

Web components are not divided - Lit-element can work within vuejs or polymer or angular for example. VueJS authored WC's can work within lit-element or polymer.

https://custom-elements-everywhere.com/ - see this for more information about interoperability (sometimes it depends on templating syntax).

You asked about Svelte and Stencil - https://svelte.technology/, https://stenciljs.com/ - those compile your code into web components - different approach than polymer that is a suite of quite a few higher-level abstractions that you might not want to pay for (20kb of js).


Thanks for links you provided.

Don't know what you mean by saying it has no relation; I've been using that site for searching components while developing my PWA based on Polymer. I can install components with yarn or npm just fine, using instructions and examples from there.


Yes, but the website is not only for polymer elements, you can find components written in other libraries too, like lit, svelte or even vue. That's what I meant - it is just a website that serves as information aggregator from bower/npm.


Problem is, web components don't provide the same thing as frameworks like React. And the performance question still hasn't been solved.

React was released in 2013, has only had minor breaking chanhes since then, and doesn't show any signs of disappearing anytime soon.


Lit-html is faster than react + vdom - and has 6kb instead of 60kb. And back in the time everyone used jquery, the arguments are always the same.


heh, I've worked for companies that hit the max on cookie size (which I think is around 60kb). For an entire framework to be 60kb would be amazing for these companies :)


Wow - 60kb for cookies is crazy.


Where's the benchmark showing this?


https://stefankrause.net/js-frameworks-benchmark8/table.html - thats old lit release there vs react 16 (react pre 16 would be slower and everyone agrees its generally fast already), on slack channel I believe I saw newer release benchmarks that are better (it also depends at which specific test you look at).

New version of repeat is interesting:

https://slack-files.com/T03PF4L4C-FCY51FZAB-c2fcf32931


I compared my usual candidates: vue, inferno, Surplus and vanillajs, and lit-html was dead last overall in almost every category. Also slower than Preact now that I checked, so I'm not sure that performance benefits are one of lit-html's unique strengths.


Yup, notice that from the slack screenshot that I posted it has speed mark 1.18 that puts it before Vue in terms of speed (which makes it plenty fast IMO, and its not even stable yet), I never claimed it is the fastest one of the bunch.

Nicoburns said that "performance question is not solved" - I think we can agree than svelte and lit are fast in general, that was the point I wanted to make that it is the implementation that matters here.


There you go, https://rawgit.com/krausest/js-framework-benchmark/master/we..., much faster than vue and react (still not inferno speed yet, but the gap is closing).


Not bad. I'm always amazed at Surplus though, that's the one to beat!


I don't know what you mean by "the performance question". A web component uses the same DOM APIs that React/etc. uses so it can have performance as good or better depending on how it is written.


The problem is coordinating rendering between components. React and similar frameworks optimise performance by batching DOM updates in one big read-compute-write cycle. With web components that don't share centralised DOM manipulation code its hard to see how that would work, and this can be a big performance problem.


obligatory xkcd:

https://xkcd.com/927/


Sure, if it works now, it'll work ten years down the line as long as they're not doing anything nonstandard.

There's a big fear that projects that become unmaintained suddenly stop working; this isn't correct.

Besides, all webapps are rebuilt in a 3-5 year cycle anyway so it really doesn't matter.


Do you feel like rewriting a bunch of webapps written in Perl/modapache around early 2000?

I know of at least one company with such a stack. Just like I know others with Web Forms, Stucts, SEAM, JSP, Zope and many other stacks in production.

Not everyone re-writes their webapps, specially in companies where software is a cost center and totally unrelated to their main business.


Sure, I'd be happy to. Converting apps from an old platform to a newer platform is reliable work, and I've done my share of it over my career. It often is structured as temporary projects, so I've had the opportunity to travel to short-term gigs in new cities while I build out platform conversion plans.

Sure, not everyone re-writes old apps. But enough companies do it to make it a decent professional specialty to cultivate. And it doesn't hurt knowing both the modern stacks and multiple generations of legacy stacks when working with large organizations. Sign me up.


> There's a big fear that projects that become unmaintained suddenly stop working; this isn't correct.

While true, it only applies if you don't want to upgrade your lower level dependencies, ever. And given that this is a React based framework, so it's not based directly on the web platform, if it's not maintained, you'll have to port the framework yourself.

Coversely, if it is maintained, you may be forced to keep up and upgrade whatever this is based on, or backport fixes if the project moves on to a newer incompatible version of the lower level dependency.

> Besides, all webapps are rebuilt in a 3-5 year cycle anyway so it really doesn't matter.

Eh? :D I still iterate on 13 or 9 year old codebases for my clients without re-building anything.


> Besides, all webapps are rebuilt in a 3-5 year cycle anyway so it really doesn't matter.

And I thought places I worked at tended to be terrible :/


"Works" and "is maintained" are two very different things.


Ten years!? It will break two months from now via some ill-thought-out npm push update.


Jetbrains would be my bet. They'll look after it even if it doesn't become the most famous library.


Jetbrains is the new Borland, but I hope that their management doesn't come up with an Inprise idea.


Thank you for this comment. I hadn't noticed that they had a ui library and I agree that they'll probably take care of it even if it's not popular. Very nice.


They're open source right? Would you expect to build your own design language, responsive/accessible components, documentation and maintain it any better than an open source solution?


These frameworks are inevitably much more generic than any in-house solution. On one side this is great, because it means that the abstractions need to be sensible - but it also means there is much more code to maintain. So yes, sometimes maintaining your own solution will be easier than maintaining an abandoned opensource solution. Of course, even better would be to use a solution which will not be abandoned.

Also note that these frameworks lock you into design & feel of their choice. This might work for some use cases and for now, but when the requirements change you often end up fighting the framework. I don't have a solution to that though. :)


> So yes, sometimes maintaining your own solution will be easier than maintaining an abandoned opensource solution.

I'd argue this depends on your needs. If you're using one of these for your consumer-facing product, perhaps so. Otherwise, if your UI is not what you're selling or your product/team is big enough to end up creating one of these from scratch anyway, then no. In the latter case, that's probably why there's so many of these to begin with.

> Also note that these frameworks lock you into design & feel of their choice.

Some of these frameworks actually let you re-theme them. For example, Ant Design can mostly be re-themed.


That's a false dichotomy. The third option is the obvious one: use a framework that will be well-maintained.


The alternative is to write all of the components yourself.

Using one of these frameworks helped us avoid that cost upfront and get the product out the door. If our company is still around in several years, I'll happily maintain it myself (or hire the original author).

EDIT: This comment assumes the framework of choice is open source.


If you pick one made by a big company, it should be fine.


That's what I thought when I integrated Google Wave into my companies workflow...

/s


I noticed the sarcasm, but, Google Wave never got out of beta (iirc) so anyone seriously adopting it knew what they were getting into.

Same with gmail which was in beta for years for some reason - probably because they wanted to avoid liability for lost data etc.


Since this thread is about frontend, what about angular 1? Everyone who was using angular 1 because it was "backed by Google" got screwed hard on that one.


I'm doubting there is any liability for lost data now that it is out of beta.


Google is the exception that proves the rule.


How's your Silverlight app working out for you? Does it still connect to your WebObjects server?


I prefer WPF :-). Touche, but Google has more of a habit of killing off perfectly good stuff. But MS does it too. With Silverlight market forces, especially HTML5/mobile and Apple policies most likely killed it.


Or Angular v1


We're very productive with Angularjs...


We've been happy with http://react.semantic-ui.com/ so far.


I liked Semantic-UI a lot in terms of looks, but the React aspect of it is separate, so even though it's done by the same people as the core team, it inherently always lags behind a bit in feature completeness. I especially ran into this with transitions and animations, and migrated to Blueprint.js instead, which I was extremely happy with from a feature-completeness perspective, but which I couldn't figure out how to theme.


It's not done by the core team. It was a separate project by separate people that was brought under Semantic UI's umbrella. That's actually the major reason for the lagging behind: Semantic UI is designed for a circa 2008 jQuery website. It's a beautiful UI, but the CSS uses a horribly dated model which obligates child elements being aware of the parent elements.

End of the day, until it's rewritten with modularity in mind it will always be a drag to properly implement it in React.


I can second this. Semantic was never set up with real modularity in mind. There is tons of relational knowledge you need to have to make anything work well.


I looked at many of these for an assessment at my company. We started a little broader with some css-only solutions as well but they tend to only take you so far; the controls are nice. Key aspects for us were (1) React-based, (2) TypeScript support (bonus for native TS), (3) Applicable to data-dense engineering apps, and (4) a broad-based, healthy ecosystem. I also evaluated Semantic-UI React.

I really like Blueprint JS but I think we'll end up building on top of Ant Design. It's a huge collection of work; they've also started to push Ant Pro which is higher-order components targeting building of admin apps (more opinionated, more than just a UI facade).


I'm in a similar boat as you. We actually started building on top of Ant. However, we first started out by building out our Admin pages and they were built with Blueprint.

I like Blueprint a lot more than Ant, but Blueprint doesn't pretend to support responsive applications[1], which was somewhat important to us. Blueprint exposes a couple building blocks (like PopOver) which really help in building more custom functionality. It actually looks like Evergreen be closer to Blueprint in this regard so I might piss off all the devs and evaluate Evergreen.

[1]https://github.com/palantir/blueprint/wiki/Frequently-asked-...


I've been using Blueprint and pairing it with Basscss for some responsive assistance and it's been successful (and a lot of fun).


I will look into this since I am on BP3 on a project and it seems that they will eventually want responsive support.


Can you elaborate on how this works? Thanks!


Gladly. Blueprint provides all of the "components" and I use Basscss to lay them all out in responsive containers.

I use Basscss' grid and flex helper classes to define how my I can create a 3-column responsive layout with something like:

    <div class="clearfix">
      <div class="col md-col-4">
        <SomeBlueprintComponent />
      </div>
      <div class="col md-col-4">
        <SomeBlueprintComponent />
      </div>
      <div class="col md-col-4">
        <SomeBlueprintComponent />
      </div>
    </div>
There's also a couple of other helpers like `max-width-*` which ensure responsiveness as the screen grows larger. Things like adding the `Classes.FILL` (which causes a button/control to go full width of its container) are useful for making things seem more like mobile (where buttons often are full width of the device, minus padding)

All in all, while it's a slight bummer than Blueprint isn't just responsive out of the box, I haven't really found that to be a deterrent to getting things done.


Have you looked at CxJS? CxJS offers chart controls and advanced data tables which makes it perfect for building admin apps.

https://cxjs.io/


I tried both BlueprintJS and Ant Design on two different projects I am handling.

While BlueprintJS is more intuitive, I find that it lacks a lot of built-in components compared to Ant Design.


Great list but missed a big one: https://material-ui.com/


Do any of these produce finished output that is less than a few kB, and works reliably in say the past two major versions of browsers? Bundle sizes are getting ridiculous.

Is there a React UI framework that focuses on tiny build size and browser compatibility?


Wouldn't any of those fit the case if you just do tree-shaking?


You have to specifically write code that supports that, so no. Look at the limitations of tree-shaking for more info.


Rebass.


Not sure what their bundle size looks like but my understanding is they're using PJAX so the site output should function without JS. Problem is good luck maintaining that stack and remaining secure. And then there's the fact there's no conceivable way it could scale properly for large sites static which would need something like Go/Rust to actually generate quickly then there's the matter of caching. Basically this all leads to headaches just in different places.


Thanks - that's a great list.

Some of them (atlaskit, MS fabric, Jetbrains, vmware etc) are geared towards building an integration withing those company's products. Whilst they can be used independently (without assets in Fabrics case, and other restrictions in the others), my take is the Evergreen (and ant, etc) are geared towards isolated products, similar to Bootstrap.

If you're building an addon for use in an Atlassian product, or an Office 365 product, these are a great way to stay consistent with the host application's look and feel.


Definitely be careful when using some of them e.g. Atlaskit because they are designed specifically for integration.

And if you use it for something else you may not comply with the license.


Another to add to the list: https://instructure.design

(Disclaimer: made by my coworkers)


Scrolling momentum is broken on iOS for me, it makes the page very frustrating to read.


Thanks for the feedback. I’m on the team building out this library. We have plans to overhaul our documentation soon and we’ll be sure to address this.


feedback: if I click on any of the sample buttons, the page is reloaded


Shopify also has one:

https://polaris.shopify.com

Personally, I've found Ant Design to be the most comprehensive, feature and behavior-wise.


Just clicked around and here's a note from the elastic/eui repo

" WARNING While open source, the intended consumers of this repository are Elastic products. Read the FAQ for details."

Doesn't instill confidence.


Hi. I maintain the library along with some others at Elastic. That warning is essentially us being good open source citizens and being very clear about how we maintain it. A lot of these other libraries are built specifically for their own products, no different then us. We just wanted to make it clear that the direction of the library and its maintenance is primarily driven by the needs of Elastic, rather than as some general community UI kit.

All that said, it certainly works fine as a general kit, and we build it with that practicality, it's just not something we officially support.

As far as stability, my team is pretty well resourced (and growing if there are any engineers interested!). We're using the library in many places around Elastic and its not going away anytime soon.

I've looked through most of the kits out there and they all have their pros and cons. Likely our biggest selling point is that it aims to be fully accessible and comes with a lot of fun charting libs. That puts its sweet spot for use in enterprise applications. It's also completely themable with about 8 lines of Sass variables.


Ace, thanks for elaborating. You could perhaps add a shorter version of this explanation to your README to make it clearer to others as well.


The point of the warning is to indicate that it's intended purpose is to be used with other elastic open source projects like elasticsearch and kibana. It's not a general purpose UI kit like the rest of those links.


https://grommet.io/ is awesome too.


I can recommend Element (the top of the list) -- I've used it on two projects now and it's been pretty refreshingly easy to use and relatively easy to integrate with (when you need to hook into components to make them act a certain way, for example a paginated table).


I made a graph showing download counts of those packages on npm - https://npmcharts.com/compare/carbon-react,material-ui,antd,...

Obviously don't use that as a sole factor to determine what to go with, but with this many options, heuristics may be helpful to narrow down which ones to further investigate


material-ui is deprecated, try with @material-ui/core.



Material-UI is by far the most complete of the frameworks in my opinion having used a bunch of them, and constantly updated. It's a joy to work with.


I posted this list. FYI: It was specifically about UI frameworks backed by big companies, not every major framework available. There are lots of purely community-owned projects too.


Wouldn't React-native-web ( https://github.com/necolas/react-native-web ) qualify into this list ?

It offers APIs compatible with React-native (which is obviously a huge time saver for cross platform UI dev).

Its disadvantage is that it does not offer (by intent and philosophy) any components outside of React native.


Yeah but how many of them are modern and elegant?



I'd also include https://reakit.io



Would also throw https://www.carbondesignsystem.com/ into the mix! We're the design system for IBM :)


What about PrimeReact? https://www.primefaces.org/primereact


From a 5 min glance, this framework looks really inaccessible. Most outlines ("focus rings") are removed and it's really hard to navigate the components with a keyboard, even as a sighted person. The focus indicator for buttons is just another shade, which is not sufficient. I was not able to set a value in the "Rating" component using my keyboard.

All those things can be fixed, but I would rather go with a library with accessibility in mind.


Here are some more, separated out by React, React Native and Universal:

https://habd.as/awesome-react-components/

https://habd.as/awesome-react-boilerplates/

Just added evergreen to the components list as it doesn't look like more than a UI kit.


Issue #1: When I scroll down the list of components, click a link to view a component and then go back to the list, I'm positioned at the top of the page, not down where I scrolled to. This is an issue with many (most?) JavaScript-rendered pages that I visit, and it's the main reason why I hate content sites (not web apps) that use JavaScript-rendered HTML.

Issue #2: Many (most?) of the form components show no indication of being selected when using keyboard navigation. This is the main issue I have with most web UI toolkits. (For example, Semantic UI is a notorious offender, even though it's frequently recommended at HN, including multiple times in the comments on this page.)

Issue #3: There are multiple problems in Firefox, including two carets displayed in each Select component.

Issue #2 and #3 almost make me miss the notices that used to be displayed at the bottom of web pages, such as "Best viewed in Internet Explorer 4 at 800x600 resolution". A lot of pages nowadays should have a warning like "Best used in Chrome with a mouse or touchscreen".


Issue #4: Go to the Tables page, click a header on the example table, the entire page disappears.


I wish people would stop making UI frameworks in <some non-standard framework name>, and instead make it web components based with vanilla JS/very light lib dependency, so that everyone can enjoy the benefit. React is becoming a bubble of its own, and it's exclusive.


My first thought was that this is a UI Framework (Evergreen) built on UI Framework (React) built on a UI Framework (js + html).

No real point here, but I do find it curious that there is this tendency to build new UI frameworks all the time.

Personally, I still like html + js (and I have used React).


3 Different things. html, css & js are like raw materials, React is processing these raw materials, and a UI components or design systems are the result you get if you mix the React process with manual labor.

The're frameworks and design systems. A React UI framework refines or enhances the React process to build UI components or design systems.

Bootstrap e.g. is 2 things in 1, it's a process/framework and design system that sits directly on top of html, css & js.


I agree very much. However there are two points that make it difficult : - Virtual Dom. It simplifies a lot the creation of components. And components that are made for a VDOM are very different from those made without VDOM in mind. - Data Binding. There are multiple ways to bind data to your components, once again this might influence the way components are made.

Those are not standard, some people like VDOM other not, and not everybody want to bind data the same way. So if we all contributed components in vanilla JS / Web Components, this still doesn't solve what should the API of those webcomponent look like.


Try https://github.com/Polymer/lit-element for an alternative to VDOM, without the VDOM part. It's reactive and uses lit-html under the hood.


This is confusing. The only difference between if this were a web component vs a React component is that the consumer would not capitalize the name. Instead of `<Button appearance="primary">` they would do `<evergreen-button appearance="primary">`. That's it.


Not at all true. Where's your onClick? People want their buttons to actually do things, right?

With Web Components you're back in the land of saving element references, querySelector, addEventListener, and string-only attributes. It sucks. If you want something more like what React provides, where attributes (props) can be objects, functions, other React elements, etc. then you need to use a library (e.g. Polymer) that's just as non-standard as React is.


Nope, you're wrong. onClick works with web components just the same way as it does with any other element. Proof: https://codesandbox.io/s/j3jmkr98pw


That uses React to attach onClick, so obviously yes. I'm saying without React. You said:

> The only difference between if this were a web component vs a React component is that the consumer would not capitalize the name. Instead of `<Button appearance="primary">` they would do `<evergreen-button appearance="primary">`.

If you're not using React, you obviously can't do `onClick={...some function here...}` with Web Components, you have to use the shitty DOM APIs.


I guess I see what you're saying that web components can seem be consumed as expected from a React app. I thought we were talking about not using React at all.

But I would expect this still would not work as expected with props like `children` or other props that accept React elements. It seems like the web component would be expecting Node instances, not React elements. Since components can decide whether or not to render their children, they wouldn't be backed by Nodes yet when the web component received them. So it seems like it'd have to know whether it's dealing with React and use ReactDOM.render directly.


Of course you can set props on a WC, it's just a DOM node. You can do everything you can do with any other standard node + exposed API. You could use jsx/vdom any other solution to set up props/events.

IMO saying 60kb of react+vdom code vs 6kb of templating library that builds on top of template literals is equally non-standard is not a fair comparison.

https://custom-elements-everywhere.com/


I realize you can set properties, obviously. Those are not the same as using attributes, which is what React's props are more equivalent to. e.g. you can't do <my-button onClick={...some function here...} />. So using it does indeed suck the same way using normal DOM elements sucks: you need a reference to the created node, addEventListener, etc.

That's what makes the grandparent's statement incorrect:

> The only difference between if this were a web component vs a React component is that the consumer would not capitalize the name. Instead of `<Button appearance="primary">` they would do `<evergreen-button appearance="primary">`. That's it.

^ wrong.


You can with lit-html/stencil, but yes you need something to take care of that for you, which is very small dependancy. WC's are NOT supposed to be consumed directly unless you do very simple things.


I guess we're all looking forward to your open source web components library!


This is already a start: https://www.webcomponents.org/


I've been working on a tiny vanilla js lib focused around web components: https://github.com/maximebf/gousse.js. It includes a set of components using Bootstrap: https://github.com/maximebf/gousse.js/blob/master/examples/u...


Web components are not supported in many popular browsers. Until they are widely supported they are not a thing. And no, Polymer and co are not polyfills for them, they are their own incompatible frameworks.

I agree in principle but it's up to browser vendors to implement specs, and it is always the same offender that is dragging his feet.


Edge and Firefox are only missing Shadow DOM and Custom Elements, which they are already developing.

On mobile Web 100% of the browsers support Web Components.

https://www.webcomponents.org/

So what are the many popular browsers you refer to? As anything else is meaningless.


> Edge and Firefox are only missing Shadow DOM and Custom Elements,

Your statement makes no sense whatsoever, they are "only missing" 2 of the most fundamental features of web components? that would actually help getting rid of all these incompatible UI toolkits? I don't call that supporting Web Components at all if you can't write custom elements natively. You obviously do not understand how the lack of support for custom element and shadow DOM affects Web Components adoption.

Not supporting 2/3 of a spec is not being compliant with that spec, obviously.


Apparently you haven't read my comment as you missed "which they are already developing." and "100% support on mobile Web" part.

Plus there are polyfills available for the meantime.

So what other browsers are many popular?


> Apparently you haven't read my comment as you missed "which they are already developing." part.

Apparently you haven't read my first comment either, since you can't tell the difference between "a spec is implemented" and "planning to implement a spec" which you obviously count as "a spec is implemented" for you or you would have refrained from making your first comment.

And no, there is no polyfills for shadow DOM or Custom Element, that's a lie. Polymer is not a Polyfill for Web Components, it's his own framework.

As for your question, I'm talking about browsers that do not support Custom Elements right now. Edge does not.


100% on mobile Web.

Firefox already on beta.

As for Edge it is already in development, and to be honest it doesn't matter with its insignificant market share.

When Microsoft employees use only Chrome at BUILD to show Azure and .NET Core MVC features, the writing is on the wall how relevant the browser is on the market.

Still you keep running away to clarify what "many browsers" means.

Maybe it is my lack of native English skills, but Edge being a single browser is far away from being "many browsers", even if we include Firefox until they get out of beta, two still does not make "many browsers".


> As for Edge it is already in development, and to be honest it doesn't matter with its insignificant market share.

Market shares are not the same across countries, clients or even industries. That's the first mistake you are making. If I develop a product, I target whatever browser my customers use, not some world wide statistic that has very little local significance.

You just don't get to ignore what goes against your point just to feel that you are winning an argument, that's childish.

> 100% on mobile Web.

Which is False, Firefox on Android doesn't support web components.

> Firefox already on beta.

Which doesn't matter if support has not shipped. "will ship" is not "has shipped". I am only interested in current support, as we speak, I was never talking about "will eventually ship" since I don't work with eventual features, obviously.


Firefox on mobile does not count for the majority of companies.

Mobile web is all about Safari and Chrome.

Again you keep avoiding to explain what "many browsers" means.


According to netmarketshare[0], on desktop[1], Edge currently has 3.8% market share, more than Safari and Opera together. Combining mobile+desktop Edge has 2%.

Edge cannot be ignored if one is serious about any kind of business: that's 3-4 out of every 100 desktop users (existing or potential customers), or 'just' 2/100 if one includes mobile.

— Honestly, it seems that you are trolling. But I post the above stats in case you are not. But I also back it up with my own personal 'anecdata': I build business-to-business ecommerce, in our specific market our users are primarily (>95%) using desktop browsers, we have many thousands of existing business relationships, we cannot mandate which browsers they use — we draw the line at having the site simply work in all "modern browsers", which obviously includes Edge.

It doesn't really matter whether it's "many browsers" that don't support Web Components, or whether it's just one major browser. For many businesses, choosing WC is simply not a viable option for the foreseeable future.

[0] No affiliation, just googled it. [1] https://netmarketshare.com/browser-market-share.aspx


You are reading it wrong, it is not me that mandates the browsers.

I have written already in multiple answers, it is the customers that decide which browsers should a given project support, by explicitly stating them on the project delivery contract.

So your customers care about EDGE, fine. Many don't.


> As for Edge it is already in development, and to be honest it doesn't matter with its insignificant market share.

Er, really? I use Edge. It's just what's standard on the Windows machine I bought. I can't imagine that it has insignificant market share...


Check how many BUILD 2018 videos presentations were done in Chrome and how many were using Edge.

As for actual market share, http://gs.statcounter.com/browser-market-share


Hm, maybe I missed the context somewhere along the lines. Are you talking about something on the developer side only? I thought the discussion was about something that works or not for the end user.


No, I mean the browsers that are part of accepting testing from project delivery contracts.

If it doesn't make the list, it is a nice to have only, in case someone on the team bothers with it.

Microsoft by using mostly Chrome at BUILD 2018 has given the sign to many businesses that it isn't worthwhile to list EDGE as a requirement.


The "polyfills in the mean time" status has continued since 2013, it's not clear that there is a lot of momentum.


Well, FX 63 ships next week, and Edge update their roadmap from considering to implementing: https://twitter.com/kylealden/status/1047240569439711232.

So Edge is the only browser missing 100% native support right now.


Edge is implementing (updated the roadmap), Firefox ships enabled WC's in closest release (it is already in the beta) I think Firefox 63 will ship in a week?.

That leaves only IE11/Edge with polyfills.


> That leaves only IE11/Edge with polyfills.

what polyfills are you talking about? And no, Polymer is not a polyfill for custom element. Please link me to a library that will polyfill the entire shadow DOM and Custom Element spec so that I can write the same code without polyfills on platforms that support both specs and only load the polyfills on platforms that do not.


https://github.com/webcomponents/webcomponentsjs - all frameworks use same polyfill.

https://github.com/vuejs/vue-web-component-wrapper

"You will also need the Shady DOM + Custom Elements polyfill." from Vue docs. Same polyfills are used by svelte etc.


https://github.com/WebComponents/webcomponentsjs

Quote from the readme.

" A suite of polyfills supporting the Web Components specs:

Custom Elements v1: allows authors to define their own custom tags (spec, tutorial, polyfill).

Shadow DOM v1: provides encapsulation by hiding DOM subtrees under shadow roots (spec, tutorial, shadydom polyfill, shadycss polyfill). "


.


What do you think youtube, ing, netflix, or EA properties use? ;)


Well, I mean, it's 1 week away from release...

https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Rel...


Well you mean it's 1 week away from release in Edge as well? Give me an ETA for Edge.


Their roadmap was JUST updated, do probably few months.


> Edge and Firefox are only missing Shadow DOM and Custom Elements, which they are already developing.

> On mobile Web 100% of the browsers support Web Components.

Wait. Which is it? Or are you ignoring Firefox Mobile?


I know that is not what HN likes to read, but iOS == Safari and Android == Chrome, and unless customer explicitly requires Firefox Mobile on the RFP, it gets ignored in acceptance testing for project delivery.


Yup, Polymer is "big" dependency, but with things like svelte, litelement or stencil you can build web components which have little overhead.

Also polyfills are separate thing from polymer - they are reused by ALL other frameworks including vuejs for example, so I'm not sure what you meant by that comment.


Personally I like LitElement: https://github.com/Polymer/lit-element

It's a super-lightweight base class for web components, and a descendant of the Polymer framework.

A Material Design framework uses this: https://github.com/material-components/material-components-w...


This is especially frustrating for job seekers. I've seen so many job listings calling for extensive experience with Bootstrap, for example. Why would knowledge of CSS and the grid system not suffice there?

It's a bit disheartening to see titles like "Ember ninja" and "Angular guru", if only because recruiters don't know that both of those things are just JavaScript frameworks.

I'm excited for Web Components but I wonder how it will play out practically. Do people put "HTML Expert" on their resumes today?


> I've seen so many job listings calling for extensive experience with Bootstrap, for example. Why would knowledge of CSS and the grid system not suffice there?

Because their current system might already be using Bootstrap, so they need someone who understands it to be able to continue the work.


Yeah, I really dislike Polymer's approach of using Web Components as an architectural pattern, but this is the exact use case they're good at. Then again, I can understand that you don't whip something like this up in a day, and support for Web Components might not be as widespread yet as a UI framework author would like.


There is 100% support on the mobile web across Safari and Chrome.


yes but real world applications often need to support more than safari and chrome, so until they are supported across the majority of them including older versions still in wide use then its still a no go for the majority of use cases.


Mobile is all about Safari and Chrome in what concerns Request For Proposals and delivery acceptance testing.

So real world customers don't care about anything else. If it happens to work, or a team member decides to go at it on their own outside project budget, it is a nice to have feature that's it.


Yes, so my point was that the authors of UI frameworks perhaps don't care about mobile only.


I am on the same boat, hence why I am on Angular and Polymer side.

Everything else that builds their little platform on top of the browser is not interesting to me.


That's radically inconsistent. Angular is not HTML, nor Javascript, rather it's its own thing -- precisely a "little platform on top of the web", to use your phrasing.


Not really, because Angular is in the migration process for Web Components adoption.

And TypeScript is a JavaScript superset with optional type annotations, which can be ignored if one so chooses.


Why are these UI frameworks tied to React, rather than working for any HTML+CSS site (as with Bootstrap)? Do they provide interactive functionality that requires React or similar?


They are not CSS frameworks in the sense of Bootstrap.

They are React component frameworks for common functionality with a unified style approach.

Something purpose-built for React is usually much better than something where React is bolted on to an existing framework, like Reactstrap (React + Boostrap) because those usually are built with jQuery and just handle state and functionality in a way that's not easy to integrate with React cleanly, so you end up re-implementing the actual functionality again.


Probably because the people making them are using React, and first and foremost they're making it for themselves.


That was my guess, but the_duke's comment makes me think there is more to it. I'll have to look at the code to see if the React components do anything more than apply HTML templates with associated CSS styles.


Some of them require run-time JavaScript, like the popovers and select boxes. And largely the value here is in the comprehensive component API, rather than just the HTML/CSS it spits out.


Not sure about interactive functionality. But it basically means it provides ready-made React components.


I think the_duke answered my question.

The reason I asked it is that, if you're building an HTML+CSS framework for use in React, then why wouldn't you separate out the HTML+CSS part, and then depend on this. That way it would be easy to re-use 90% of the work, if you then want to use the components with Vue or some other framework, or even for plain static pages.


Bootstrap needs jQuery for anything that requires interactivity


Don't ask questions like that. /s


Evergreen looks quite nice, but their website isn't responsive and that gives me pause when considering it for my own projects. The components themselves may work fine, but I can't be sure without digging in further.

Just something to consider if you're looking at using Evergreen.


"Currently there is no opinionated way to construct responsive layouts in Evergreen. In the case of responsive layouts you might want to simply use a div with a class name and use breakpoints in CSS — or potentially a CSS-in-JS solution."

https://evergreen.segment.com/components/layout-primitives


Responsive design isn't just adding breakpoints.

It's responding to the device and the ways the user will interact with it. For example, the combobox example in Evergreen doesn't actually use a <select> in the background, so users on mobile devices will actually have to use the dropdown implementation rather than the browser displaying a proper native mobile select. That's a much worse experience. Not to mention Evergreen will be completely inaccessible for users who need assistive technology, which potentially poses legal issues...


Did you try it on mobile? It actually does seem to use the native selector and not the custom one for me


I did, and it doesn't on my Android phone.


That's a minor thing but when I press the back button on one of the documentation pages it takes 6 seconds to go back (first it changes the title of the tab then it seems to wait for 6 seconds, probably parsing and running several MB of JavaScript). Sometimes the tab titles is blinking and displaying "Evergreen" and "Components - Evergreen" very quickly during these 6 seconds.

You'd think in 2018 going back to a page would be a solved problem, but apparently each new framework needs to re-solve this in a new orignal way.


This doesn't happen for me, it is pretty quick. I am in India and on a 40 Mbps connection.


My connection is fast enough too. I'm on Firefox though, so maybe that's the "issue", if their framework is designed to work mostly on Chrome and not the other browsers.


Yes, I am looking at it in Chrome on Ubuntu.

Just tried it in Firefox 62 on Ubuntu. Works good there too.


I've wondered about React, although I haven't used it myself. I know that the new Reddit was written using React components, and it's very slow. Is that a React problem (i.e. is it hard to write fast web apps) or is it a Reddit problem (or both)?


It's not a React problem. React runs Facebook, Instagram, and mobile Twitter, for example. But it's possible to build inefficient React implementations. Reddit rebuilt their front end from the ground up. It is possible they have front end issues there. Some flame chart analysis on Reddit's current front end and old front end would reveal the source of the problems.


While I agree React isn't the issue here, you chose horrible examples. Loading Facebook on my computer (especially trying to open a chat window) brings my computer to a knee. And using twitter on mobile browser you quickly learn how the spinner looks.


I haven't had performance issues on Facebook in quite some time. And Twitter works like a charm on my Nexus. I'm wondering how much of your issues have to do with either round trip latency or network issues.


Using FB on my 2014 Macbook Pro is slow as hell and my CPU starts heating up causing the vents to spin up.

It has nothing to do with the round trip latency, the CPU is pegged.


The Twitter PWA works fine on my crappy $200 Android phone.


Same issue here, I think it takes on average 30 seconds to open Messenger. Facebook is similar. Twitter is also slow.


React is fast. If you are not experienced in react you'll make a mess because they work against its principles.

To me the Reddit web app is fast, the show part I think is the server side.


There may be some fast components in the Reddit web app, but I think there must be a valid reason why so many users are switching to the old Reddit (not just because of the way it looks, but due to performance complaints). I just went in and even scrolling through Reddit comments is laggy. Switching to old mode is like day and night.


they're sticking with the old reddit because the information density is much higher. it's a design problem.


Not only that, for me in Safari the new reddit barely works and is not loading things very fast or sometimes at all.


This could also be due to a poor implementation of event listeners for scrolling, e.g. not throttling, which isn't necessarily a React issue.


Good point.

I built a SPA recently and learned pretty quickly to replace `on('scroll', handler)` with a set-flag-and-sweep-at-slower-interval solution to bring down CPU usage.

While something like React alone isn't slow, building a SPA means you're taking on a lot more responsibility, and there's a lot more things that can go wrong.

Even something like "when user clicks an item, make loader spin until server response, and then render the detail page with the data" can feel much, much slower even though it's not from a clock-time standpoint.

Aside: Using a slow device as your main testing device is a life-changer if you want to catch this stuff early. It's hard to ignore this stuff when you have to feel the pain yourself on every refresh. Good reason to always keep your old phone around.


The new Reddit design is often much slower loading the first time than the old one. It's performant after that, but that first load is annoying.


I just had to come back to this comment after testing in a couple of browsers, focusing on Safari and Chrome. Going to https://www.reddit.com/r/whatisthisthing/comments/9oz5sa/wha... and scrolling is OK in Safari but actually pretty laggy compared to old mode. It's definitely not how a modern web site should perform. Testing with Chrome, it was fast in the beginning, but if you scroll up and down for about 15-20 seconds, CPU load goes up and my laptops fan start spinning.

So no, I do not believe reddit's new design is "performant" at all.

One has to wonder - if Reddit's engineers can't get React right (I'm sure they hire smart people), is it really not a problem with React in the end?


React is not fast, clearly the simple idea of having a virtual Dom is very costly compared to do things by hand. However for a large scale app react makes it more easy to reason about and keep it maintainable, components are far easier to implement, etc...

So for many people, the benefits you get on the development side outweight the performance overhead


There is an overhead, but the main problem with the new Reddit is not that it was made in React, but that it's a massive fuckup. Not only from a programming perspective but also design and UX.


Given how much they push you to use the app, it's possibly intentional.


I should have pointed out that I was referring to the new Redesign of the desktop web. I never use the mobile web.


always hilarious to see the dumb dependencies that these projects have

https://github.com/sindresorhus/arrify

https://github.com/JedWatson/classnames


While I can understand your skepticism on the first one, the second package is actually very useful. It doesn't just concatenate strings filtering out falsy values, it supports the whole old AngularJS class format. You can, for example, pass an object {string:booleanish} and it will add only the keys whose values are truthy.

Pretty neat, actually.


> You can, for example, pass an object {string:booleanish} and it will add only the keys whose values are truthy.

Why is this something you can't do on your own in a few lines of code?

  const classNames = (o, c=[]) => {
    for (let k in o) if (o[k]) c.push(k) // booleanish
    return c.join(" ")
  } 
This is not cool at all! Why import a trivial function over NPM to do this for you? Better to lower your dependency count and have a "util.js" file for helpers like this.


I am starting to follow Sindre's philosophy [1] more and more. I published this morning `fch` [2], a 10-15 LoC library (note: undocumented for now). I will test it well and make sure it works everywhere. In exchange, I removed basically the same code from 3 projects (so far), some of them with subtle bugs.

The cost of using it is the same as locally, and creation cost is lower per-project if you let npm manage your own libs. Plus, bug fixes are automatically propagated.

[1] https://github.com/sindresorhus/ama/issues/10#issuecomment-1...

[2] https://github.com/franciscop/fetch


Your little utility here doesn’t cover the whole 'classnames' API.

  export default function classNames(...args) {
    return args.filter(valid).map(single);
  }

  function valid(arg) {
    return arg && (!Array.isArray(arg) || arg.length);
  }

  function single(arg) {
    if (typeof arg === 'string') {
      return arg;
    } else if (Array.isArray(arg)) {
      return classNames(...arg);
    } else {
      return Object.keys(arg).filter(k => ………
This is getting similar…


> Your little utility here doesn’t cover the whole 'classnames' API.

Thats partly the point. The whole API doesn't really need to be covered in order to achieve the same utility. I think the library clearly over-engineered the simple task of string concatenation, and their API is redundant.

Their API caters to too many styles and that increases its complexity. It takes 2 seconds to grok the two lines in my utility, whereas it takes 5 minutes to make sure you know all 50 combinatorial ways to concatenate a string with the classNames library. There is too much indecision in the API, so they decided to support everything they could think of. Now I have to be ready for the possibility that the 5 people on my team can't agree on a convention simply because the library allows every possible convention one could desire.


You don't "agree" on a convention, they have different use cases. Sometimes you'll want to merge a bunch of class names so you use array-style. Other times you have class names that have prop dependencies so you use object style and finally you'll want to merge in some always-on defaults so you have string style. You'll often need to combine them, depending on use-case.

That's a whole lot of complaints for 50 lines of code.


> Sometimes you'll want to merge a bunch of class names so you use array-style

> Other times you have class names that have prop dependencies so you use object style

> merge in some always-on defaults so you have string style

There's some irony here -- all of this just to avoid dealing with string templates:

  `${class1} ${class2} ${class3}`
> You'll often need to combine them

Need is definitely not the right word here. The classNames utility is a completely unnecessary abstraction.


You want `undefined` and `null` to show up in class names? You'd at least need `${class1||''}` and your solution will grow in cases from there despite your one-liner.

Your solution doesn't do anything I'd expect someone wants that lib for, like merging in a map of classes.

I don't think this lib is the best pyre to die on to make a point I generally agree with.


> There's some irony here -- all of this just to avoid dealing with string templates:

By that argument, we can just avoid everything by not making our apps dynamic!

> The classNames utility is a completely unnecessary abstraction.

The only necessary abstraction in programming is assembly since 0's and 1's are hard to reason about. The "need" in this case refers to needing to mix different primitives to make your app dynamic. Your arbitrary example above doesn't do anything because you still have conditional logic to determine what class1 class2 and class3 are, you are just doing a bunch of ugly crap in the render function rather than abstracting it. Or implementing your own version because you're smart.

It's a stupid hill to die on here... you want to argue about importing the entire lodash library because you like .chain, have at it. But I guess you can keep patting yourself on the back for avoiding importing a no-dependency 50-line library.


Ok, no one is shoveling it down your throat. Just avoid it.

But be prepared because it is the de-facto standard way of building classNames in React, also because it was part of the standard utilities provided by React.


I get the "dependency hell" issue in Javascript world, but why would I rewrite this particular utility? It's well tested (both unit and field tested), includes edge cases and has zero dependencies. As a dependency, I will also get any future bug fixes or features if I wish to. An even better example is lodash. Would you really rewrite every util you need just for the sake of not having external dependencies?


Probably because the scope is so small that you _could_ actually rewrite it yourself. And then together with all these other toy libraries, stick it in one big one that covers everything you need in terms of convenience functions.


So much this. It's 30 lines of code. The remaining code is comment fluff and 15 lines dedicated to the various types of export utilities (AMD, NPM, window). Seriously this is such an odd package to start these arguments with.


Playing devil's advocate, why is lowering your dependency count a good thing?


Dependencies have cost. You have to monitor for updates, notify the maintainer(s) of any bugs, keep an eye out for security vulnerabilities, and sometimes (gasp) even step through them with a debugger.

Doing that for one dependency is bad enough, but for 100s it's a nightmare.

Personally, I prefer to just pull the pieces I need out of an open source library (unless it's very well maintained, or huge). It's like doing a code review at the same time, so you're aware of what's going on in your application.


Copy/pasting has a nearly identical cost (aside from notifying the maintainer), except you have to catch all of them, you removed an easy upgrade path when other people catch the issues and you're spending vastly more time "code reviewing" every dependency you have rather than actually producing the software you're trying to write.

Don't know about you, but we have actual goals and I'd never meet them if I tried your method.


I think he might be talking about trivial dependencies, like leftpad, classNames, arrify, etc. In the case of trivial dependencies, rolling your 30-line "util.js" file to remove 3 dependencies is definitely worth it. No one is suggesting you roll your own diffing algorithm.


I think I already responded to you elsewhere, but in case I'm incorrect: No it is not worth it. You are re-inventing the wheel so you can pat yourself on the back. Nobody hires a software engineer to write leftpad. Rolling your own diffing algorithm is exactly what actual engineering entails.


> You are re-inventing the wheel

Not quite, that would imply time and effort. I'm talking about reinventing the toothpick (2-3 lines of code), which is much different than reinventing a complex library for the sake of reinventing it.

> Rolling your own diffing algorithm is exactly what actual engineering entails

That's nice, but you're addressing a straw man. No one actually said rolling your own diffing algorithm is not what engineering entails. It was said that no one is suggesting you recreate a non-trivial dependency for the sake of reducing your dependency count.

I can use it in an example if it helps: If you are hired to write a basic website and you choose React, then you probably shouldn't reinvent React as your first step in writing the website. React is a fine dependency because it does a lot.

Humor me -- the next time you use classNames for a small project, try and see if you can't replace all of your calls to classNames with very basic template strings or other trivial code. It should not take any effort. For example I've seen things similar to "classNames({myClass: true})" in code before. Can you see what is wrong with this line? When people get comfortable with abstractions, they completely forget how to write the simplest code.


> Not quite, that would imply time and effort. I'm talking about reinventing the toothpick (2-3 lines of code), which is much different than reinventing a complex library for the sake of reinventing it.

Re-inventing 1000 versions of a tooth pick is reinventing the wheel.

> That's nice, but you're addressing a straw man.

You keep using that term and I'm not sure you understand what it means.

> It was said that no one is suggesting you recreate a non-trivial dependency for the sake of reducing your dependency count.

And my argument is that dependency count is one of the dumbest metrics to be interested in. Size, sure as that impacts bundle size, which in-turn, effects latency. But "count" is meaningless.

> Humor me -- the next time you use classNames for a small project

I use styled-components exclusively for React projects now.

> For example I've seen things similar to "classNames({myClass: true})" in code before.

So? Bad code is bad, that's not a library failure. Now that is a straw man.

> Can you see what is wrong with this line?

Of course I can, because I'm actually good at my job. I also wouldn't do that. Using your toaster in a bathtub is also REALLY stupid, but that doesn't mean we should ban toasters.

> When people get comfortable with abstractions, they completely forget how to write the simplest code.

No that's called laziness and it has nothing to do with dependencies. You have twice in this thread accused me of straw men inaccurately, and now wrote a paragraph dedicated to a huge straw man.


> Personally, I prefer to just pull the pieces I need out of an open source library (unless it's very well maintained, or huge). It's like doing a code review at the same time, so you're aware of what's going on in your application.

To quote yourself: Doing that for one dependency is bad enough, but for 100s it's a nightmare.

'Forking' a project's dependencies (which is effectively what this is...) is often fraught with as much trouble as just having the damn dependency in the first place.


I think the thing is that the one library you are forking contains 50 frivolous ones, so you’d really only be doing it twice.


Replace “dependency” with “code / function” in your post and you will see the problem.


What’s nice about it is that a lot of projects use the same util, meaning it is very easy to read or edit if you are familiar with the library. If everybody writes a custom function you will need to learn how to do classNames separately in every project you work on.


Yeah this argument falls flat in the case of classnames where we're comparing reading a two liner function with reading a page of docs for a library.

It's like everyone in JS land is allergic to writing a piece of code that isn't just playing lego with things written by a real developer.


Yeah, my React code is currently littered with conditions and `classNames.join(' ')`. I'm going to start using this library.


In ideal world all functions should be pure and be a dependency and all code should be just pure functions.


Second one is used only once in the code base to concat two strings together afaik


Curious what your issue with classnames is? Is it just because it’s a small and simple module (50 lines of code)?


I was curious so I checked out their Github page. I found this example:

  classNames('foo', 'bar'); // => 'foo bar'
  classNames('foo', { bar: true }); // => 'foo bar'
  classNames({ 'foo-bar': true }); // => 'foo-bar'
  classNames({ 'foo-bar': false }); // => ''
  classNames({ foo: true }, { bar: true }); // => 'foo bar'
  classNames({ foo: true, bar: true }); // => 'foo bar'
  ...
  var btnClass = classNames({
    btn: true,
    'btn-pressed': this.state.isPressed,
    'btn-over': !this.state.isPressed && this.state.isHovered
  });
Look like the button example is a good enough convention for me, I don't need any of the other conventions. Can anyone tell me why this is not sufficient?:

  const classNames = (pojo, c=[]) => {
    for (let k in pojo) if (pojo[k]) c.push(k);
    return !!c.length && c.join(" ");
  }
Do I need array-flattening support, multiple argument support? The size of this library probably comes from it supporting a handful of different coding styles. I would say the size (50 lines) is too large, if anything. Dependency worthy? I'm not convinced. I am very much so against requiring trivial utility functions from other people. Roll your own if it's trivial! It's better than depending on something over the network.


My usage is typically

  const cmpClass = classnames('componentsMainClass', props.className, { dynamicClassesHere });
I like that the component's main class stands out and is easy to find, that allowing the consumer to pass along their own class is trivial, and that the dynamic classes are grouped together.

So I'd argue multi argument and falsy thinning are welcome features. I've never used array flattening.

Does it really need to be a dependency? I guess that's a matter of opinion. I like that the various React projects I deal with on a regular basis all handle classes in a consistent manner. I also don't usually mind dependencies that don't pull the entire world in with them.


> const cmpClass = classnames('componentsMainClass', props.className, { dynamicClassesHere });

This is a matter of convention. Another, equally valid convention:

  classNames({
    mainClass: true, // first key is main class
    [props.className]: true, // derived
    otherClass: true, // rest
    yetAnotherClass: true // ...
  })
At the end of the day, everyone has to learn their codebase's convention, and that's all that really matters. One convention isn't better or worse than any other, but it's best to have one and stick with it. I don't need a library which supports 10 different conventions if my chosen convention only requires 2 lines of code. Your convention could be implemented in a few lines of code, as well, and then you'd be forced to stick with it, which is probably better. Using this library, 5 different developers could be using 5 different conventions. The helper function I suggest forces a single convention, which lowers complexity.


Readability is important, your example above would need to be

  classNames({
    mainClass: true,
    [props.className]: props.className,
    otherClass: somePredicate
  })
The props.className one in particular is pretty garish. Probably should do !!props.className to help explain intent a bit, which adds to the tedium. Once you've added falsy thinning and arbitrary arguments, you're 99% of the way to classnames.


Roll your own, untested function vs a small, widely used library with a well-understood, well-tested API that your devs have a good chance of being familiar with already. I too want to avoid bloated npm dependencies but this seems like a fair engineering trade-off..


This is a trivial function, your argument applies to complex utilities. It is piss easy to roll your own, and it's not worth introducing a potential attack vector via a new dependency. In this case, if your devs can't keep up with your classNames function, fire them, because it's trivial.

  it("should work with no classes", () => {
    expect(classNames({}).to.be.false
  })
  it("should work with a single class", () => {
    expect(classNames({a:true})).to.equal("a")
  })
  it("should work with booleans", () => {
    expect(classNames({a:true, b: false}).to.equal("a b")
  })
  it("should work with falsy and truthy values", () => {
    expect(classNames({a: 5, b: ""}).to.equal("a b")
  })

This isn't redux. It's a trivial utility function. Your kind of thinking is too often applied without thinking. Before depending on someone's code, ask yourself if you can roll your own in under 5 minutes. The answer could easily be yes. There is no good reason to depend on someone else's code if it's trivial. Having more dependencies than you need is a cardinal sin that way too many javascript developers commit.


If you write 100 ~50 line "trivial functions" you've now written 5000 lines of code that doesn't actually solve your underlying problem, it just makes it slightly easier.

And you can't write this particular utility function in 5 minutes and support all the uses-cases, particularly if you are going to write a bunch of unit tests.

The reason to depend on someone else's code in trivial use-cases is entirely because they are trivial. There's nothing you're doing aside from wasting time by writing it. lodash is literally a massive library of mostly "trival" functions that no one is every going to write themselves because WHY waste the time?

The only cardinal sin at play here is thinking that wasting your time reinventing the wheel is time well spent. This approach is what I'd expect from either a very young developer or a very self-centered one.


> If you write 100 ~50 line "trivial functions

No, we're talking about 2-3 line functions. Stop arguing with a straw man. You're taking what you know to be true about complex code, and then asserting that those things are also true with simple code. That doesn't work.

> And you can't write this particular utility function in 5 minutes and support all the uses-cases

The beauty is that because we are rolling our own function, we only need to support the single function signature we decide we're going to stick to in our codebase. Supporting every use-case becomes a moot point.

The author of the library has to support the 10^5 people who use his code, meaning he's more likely to merge silly pull requests like "should take objects", "should flatten the input array", "should allow multiple arguments", "should work with X", "should do Y" because people have different styles.

> The reason to depend on someone else's code in trivial use-cases is entirely because they are trivial. There's nothing you're doing aside from wasting time by writing it

It only takes time if you are not able to do basic programming. I find basic programming to be a much more enjoyable and productive approach than depending on potentially dozens of trivial libraries whose APIs are not the way I would design them, and could change at any time. Learning dozens of APIs takes just as much time as implementing them for a certain set of functions. That set is different for everyone, but it is not the null set for anyone.


> No, we're talking about 2-3 line functions. Stop arguing with a straw man. You're taking what you know to be true about complex code, and then asserting that those things are also true with simple code. That doesn't work.

The library in question is literally 50 lines of code. About 30 when you remove the exports and comments at the top. I find it somewhat ironic that you are so opposed to using utility libraries and you didn't even bother to look at the one in play here.

> The beauty is that because we are rolling our own function, we only need to support the single function signature we decide we're going to stick to in our codebase. Supporting every use-case becomes a moot point.

No it doesn't. All the use-cases are useful. You use strings when you need default classes and objects when you have conditional classes. You can't implement both of those in two lines of code.

> The author of the library has to support the 10^5 people who use his code, meaning he's more likely to merge silly pull requests like "should take objects",

It's always taken objects as properties and for good reason: it's a clean way to separate conditional classes from unconditional ones.

But sure dude, all those features are insane. Put his code up to a solid 30 lines. Really saving the bacon by rolling your own that doesn't do the same thing.

> Learning dozens of APIs takes just as much time as implementing them for a certain set of functions. That set is different for everyone, but it is not the null set for anyone.

Yeah, that's why everyone writes their own lodash. It's just a set of trivial functions.


Yeah and if you've analysed 100 sets of docs for 100 dependencies you've done a ton more work than writing 100 trivial functions.

Why does everyone in JS land treat dependencies like they're just some free magic, as if an intimate familiarity with the source code is injected into your entire team's brains the moment you type 'npm install'? I've worked with far too many people that blow out the package.json file for every little thing then wonder how every other dev on their team seems to be paralysed by the smallest task.

Every time someone on your team runs into a dependency boundary they need to stop reading code, pull up a browser, and start reading docs. You can't trace the path of execution through a black box dependency, which means if you use a bunch of them in one place your developers are going to have to hold a hell of a lot of information in their head while they analyse that code. If they drop something, it's back to the docs again. At the extreme, it's a context switching nightmare.

Dependencies cost time, effort and brain power. Make sure you're getting enough in return.


You're absolutely wrong. If reading the docs were harder/more work than writing the code we'd have 100s of implementations of lodash. Instead people use lodash.

Dependency boundary? If you can't figure out what a function called classNames does in the context of a React render function in which the output of classNames is put as a value in to "className" attributes, you need to find a new job.

Dependencies cost time, effort and brain power when they actually require those things. Be thoughtful when using something that actually requires investigation. But honestly, a trivial function should be self-documenting or it really isn't trivial, is it? If I had an npm library called array-flatten are you seriously going to read the docs, or assume it flattens nested arrays?


I never said anything about writing the dependency. I'm talking about reading and writing code that uses it.

Of course it's easier to read a trivial function than the docs for a trivial function. That's what makes it trivial, it's not abstracting away anything meaningful. And of course I can easily figure out what classNames outputs.

You know what I can't figure out trivially? What inputs it takes. It's a polymorphic function. Me and Bob load up a new codebase, I open a few files and see classNames used a couple of times with an object parameter. I can now be pretty confident what the API of the function is. Bob opens up a couple of different files and sees it used with an array parameter a few times. Now he's pretty confident he's got the hang of it too. We both go off to write new components. I've got a bunch of this everywhere:

{ foo: true, bar: true, baz: true }

And Bob has a bunch of this everywhere:

[foo ? 'bar' : null, baz ? 'boop' : null]

Bam, inconsistent code. Could have easily been solved by reading the docs before using something though. And hey, at least we'll both remember for next time...

...Unless our team imports 100 of these libraries and tries to enforce a consistent use of them across the project.

There's only so much API surface area one dev can keep at the front of their mind while coding. Good devs understand this and minimize it. Bad devs pile in trivial dependencies because they don't understand their cost.

Oh, and how do I know whether flattenArray is recursive or not? What if it is and I only want to flatten one level? Does it take a second integer parameter? Or an options object? Since we're talking about JS, does it flatten Array-like objects? Is that the same API or a different one? It's almost like your example proves my point...


> Bam, inconsistent code

Yeah, and in CR you should be told not to use the object form when you have "true" as the value, as it's pointless. That's what string form is for. The "docs" are literally 5 lines where you learn you can send object literals, arrays and strings.

> There's only so much API surface area one dev can keep at the front of their mind while coding. Good devs understand this and minimize it. Bad devs pile in trivial dependencies because they don't understand their cost.

Yes, because if you implement a similar feature the remaining members of your team all know it through osmosis. The surface area of these functions is tiny, but apparently your implementation requires no investigation by anyone.

> Oh, and how do I know whether flattenArray is recursive or not?

Holy cow, man. Do you literally hand-implement EVERY utility function you've ever needed?

> It's almost like your example proves my point...

Your point seems to be: you can't manage to infer ANYTHING from a function signature AND that apparently somehow your team members can ALWAYS infer everything needed from any function YOU write.

Use code inspection and you'll never open the docs for flattenArray or anything like it again. If this is the amount of effort required for flattenArray for you, how to you actually use large libraries with HUGE surface areas?


> Yeah, and in CR you should be told not to use the object form when you have "true" as the value, as it's pointless. That's what string form is for. The "docs" are literally 5 lines where you learn you can send object literals, arrays and strings.

What a dumbass argument. So instead of writing a one line abstraction, I should invest a bunch of CR time explaining to my whole team which of 3 different APIs they should be using in this dependency I've brought in?

> Holy cow, man. Do you literally hand-implement EVERY utility function you've ever needed?

No, just the trivial ones. Have you been actually reading this thread?

> Your point seems to be: you can't manage to infer ANYTHING from a function signature

No, my point is that you can't infer the full API of a function from the arguments passed to it's invokation when the function is polymorphic.

> AND that apparently somehow your team members can ALWAYS infer everything needed from any function YOU write.

If the function is trivial, which is exactly what we've been talking about this whole time, then No. Fucking. Shit. The function is trivial and they have the source code right there.


> So instead of writing a one line abstraction, I should invest a bunch of CR time explaining to my whole team which of 3 different APIs they should be using in this dependency I've brought in?

It's not a one-liner because it doesn't support the same feature set. It supports a basic use case that may be great for trivial apps, but in the real world it isn't.

> No, just the trivial ones. Have you been actually reading this thread?

And said trivial ones must still be "learned" by your co-workers. You've saved exactly zero time.

> No, my point is that you can't infer the full API of a function from the arguments passed to it's invokation when the function is polymorphic.

You can with a glorified text-editor these days with Code Inspection. I guess that's advanced stuff we shouldn't expect our co-workers to use?

> If the function is trivial, which is exactly what we've been talking about this whole time, then No. Fucking. Shit. The function is trivial and they have the source code right there.

Yet, if the function is trivial AND is imported via npm, it suddenly requires reading docs. On one hand you argue "triviality requires reading docs" and then suggest that you can implement a similar trivial function and everyone can just look at the source code.

And you don't see the irony here.


You're conflating a trivial function with a trivial API. The whole reason I jumped into this thread is because classnames is a great example of a trivial function with a non-trivial API. Yes, you do need to look up either the docs or the implementation to understand how to use it. I think my past examples made that clear.

What I'm saying is that it's EASIER to understand the source code than it is to understand the documentation for classnames. That's because it abstracts nothing away. It's replacing one simple API (template strings) with another one that's very similar and of roughly the same power. By turning it into a dependency you're adding an artificial barrier between it and your code base, that makes it harder for everyone to grok. Not much harder, but enough to be a pain in the ass in any codebase where that same tradeoff is made over and over.

If you can't understand that, then I don't know what to do for you. Keep writing shit JS code and making the web worse than it already is.


there is no need to support all use-cases.


There is if you use them all? We're talking about strings, arrays and objects as inputs. ~30 lines of actual code.


    it("should work with booleans", () => {
      expect(classNames({a:true, b: false}).to.equal("a b")
    })
Shouldnt this just equal "a" though? See, already a bug in your homegrown solution!


My test would fail, and I would fix it. + 2 seconds. Actually, the next test has the same problem. 2 more seconds. I'm gonna be in trouble with my boss!


No, your test wouldn't fail because you wrote your code already being confident it is correct and went on. The bug would surface later in your team, somebody else in your team not familiar with your code would spent hours figuring out what is wrong, will consult you about your intentions when you wrote the code etc.


No, the test would fail in this case because the code was written properly because it was a TRIVIAL 2-line function (see above).

A few people in this thread have regurgitated the same reasoning you have. The problem is that your reasoning is NOT an invariant under complexity. This reasoning does not apply nearly as much to trivial utility functions such as:

  const isObj = o => !!o && typeof o === "object"
and classNames, etc. as it does to larger, more complex code.

> will consult you about your intentions when you wrote the code etc.

No, no they won't. No one will consult me on what my 2-line classNames functions does. It's 2 non-obfuscated lines. These aren't undergrads in CS101.


We’ve been doing:

  const classNames = [
    “btn”,
    this.props.isSelected && “btn-selected”
  ].filter(Boolean).join(“ “)


  const arrify = a => a && (Array.isArray(a) ? a : [a])
vs. introducing a potential attack vector.


arrify(null) returns null, unlike the arrify library . I expect that a function which turns things into an array returns an empty array as fallback. This ist just an example for why one would favor well-tested utilities over re-inventing the wheel (not that I would use arrify as a dependency myself).


> This ist just an example for why one would favor well-tested utilities over re-inventing the wheel

No, it really isn't. The library does not dictate how things should be done, that's the fantastic thing about using your own utilities. In my implementation, we return the value itself if it's falsy. In yours, we return an empty array. Again, trivial "fix" (not that there's anything to "fix", it's a matter of convention, not correctness).


Is there a way to see what code in the project actually uses these dependencies? I gave up on learning Typescript for another 6 months after a starter template dragged in 400 dependencies.


Why would that matter for learning typescript..?


If using typescript requires 400 dependencies, it’s a non-starter, and learning it is off the table until your boss forces you to.


A Microsoft template for Vue+Typescript (which I've since learned was unmaintained) pulled in 400 dependencies.


Most low effort way is to search the repository on GitHub for the require.

Also worth noting the ones I listed aren't transitive dependencies. Those are both explicit dependencies of this project


Does anyone knows a react ui framework which also includes concepts for more high-level interfaces? Not only atoms and molecules, but also "organisms" and "pages" as a compound of several components?

I feel like, a lot of ppl still create horrible UIs based on good components, because they lack the bright overview.



Great, but not a single clickable item works in Safari :'D


Are you on macOS? I can open the dialog via button example here (https://evergreen.segment.com/components/dialog) on macOS Safari 12.0.


It was same here, latest macOS/Safari. Weirdly enough now I visited the page again and it works.


Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: