Why Grommet 2.0?

Douglas Gennetten edited this page Aug 18, 2017 · 7 revisions

As you may know, Grommet core team is already working on the next major release, we are calling it NEXT. So you might be asking questions like: Why the change? What is going to break? When is it going to be released?

Well this wiki page aims to answer all these questions 😄

Motivation

The primary goal of Grommet 2.0 is to improve the Developer Experience (DX). Grommet 1.X has been around since October 2016, and we have received a lot of good feedback during these 9 months. We heard things like "grommet looks like it will be such a great UI framework… just not there yet…" and "grommet is difficult to customize". So, based on the community feedback and our experience developing apps using Grommet, here is a compiled list of things that are painful today using Grommet:

1. Need special config to include style

One of the most frequent requests we receive is to help folks that are having a hard time including the SASS config for Webpack, especially because we currently use inuitcss and you need to configure webpack SASS loader to look inside node_modules for our style dependencies. This also makes it harder to integrate with existing dev environments for React applications, for example react-boilerplate, create-react-app. They often don't come with SASS support, and you need to customize them to make Grommet work. We created separate repos with reference implementations which helped but did not solve the problem (e.g., grommet-react-app, grommet-react-boilerplate).

Given that, developers usually end up using the minified CSS which is difficult to customize (not to mention the developers that gave up on even trying Grommet because they couldn't get it to work with their favorite dev environment 🙊).

2. Customizing styles for existing components requires SASS knowledge

After spending some time figuring out how to create a basic Grommet app, developers now need to know SASS in order to customize Grommet to match their brand. All the SASS variables are global and can be used virtually anywhere in any component. This makes it difficult to even add documentation for it. Another common request from the community is a reference on "How to customize Grommet?".

3. Styles for existing components are global

Currently, all styles are imported in Grommet even if you are just using a handful set of components. There is a way that you can only import what you need, but the Global nature of SASS makes it difficult to keep things self-contained.

4. Theming is done during build time

Customizing Grommet often means that you want to create a theme where you would replace the SASS variables to match your brand. If you want to run an application that has two themes running concurrently, you would have to create two different react apps. This limitation exists because the styles need to be compiled to CSS before it is used in the browser. Although uncommon, it is a possible use case that we don't easily support.

5. Some components have too much abstraction (e.g., Card, LoginForm) which makes customization even harder

LoginForm, for example, is a useful component, but it quite opinionated. This leads to the desire to customize things. Currently, the way we can customize it is through props, but doing so can lead to an overly complicated propTypes which will be hard to maintain and use.

6. Click handlers don't use Button or Anchor

Distribution, for example, has the onClick prop where the click handler is added directly to the DOM node. This means that we need custom code to make the container accessible. This custom code is added inside each component that supports onClick, which makes the code base unnecessarily bigger and complex.

7. Lack of tree-shaking support

Grommet 1.X does not provide the ability to easily remove components that are not being used. Our current recommendation is to import components using its full path import Button from 'grommet/components/Button';. Our community wants to import components using member styled imports import { Anchor, Button } from 'grommet';. Although this is supported today, it is not recommended since it will include everything inside grommet in your final build. The bundle size will be significantly bigger with this styled import.

8. Need for more sample applications and reference on how to properly use the components

grommet.io already has a lot of good documentation and reference implementation. But, we still believe we need a better approach to not only document the component properties but, more importantly, show valid combinations of both properties within a component and component nesting.

What is coming next?

We are excited to replace SASS with styled-components. Just by using it we are solving items 1 to 4. Styled-components are local by default; you can easily customize it with a theme object in the React context, or even as a prop in your component. Styled-components does not require any build tools like Webpack or RollUp. For basic theming capabilities you don't even need to know or use Styled-components. Here is how the code for a Button will look like in Grommet 2.0:

import { Button, Grommet } from 'grommet';
<Grommet>
  <Button label='Add' onClick={() => {}} />
</Grommet>

The only requirement here is to import the components and have your module bundler process JS files with babel.

Compare that with:

import 'grommet/vanilla/index.scss';
import App from 'grommet/components/App';
import Button from 'grommet/components/Button';

<App>
  <Button label='Add' onClick={() => {}} />
</App>

Here you need an additional loader to process SASS files.

Customizing themes is as easy as providing a JavaScript object.

const hpeTheme = {
   button: {
    border: {
      radius: '0px',
    },
    colors: {
      accent: '#ff8d6d',
      secondary: 'rgba(51,51,51,0.6)',
    },
    extend: 'letter-spacing: 0.04167em;',
  },
};

import { Button, Grommet } from 'grommet';

<Grommet theme={hpeTheme}>
  <Button label='Add' onClick={() => {}} />
</Grommet>

Notice the extend property inside button object that allows you to augment the button with additional styling for your theme.

Compare that with:

index.js

import 'index.scss';
import App from 'grommet/components/App';
import Button from 'grommet/components/Button';

<App>
  <Button label='Add' onClick={() => {}} />
</App>

index.scss

$button-accent-color: #ff8d6d;
$button-secondary-color: rgba(51,51,51,0.6);
$control-brand-color: #049371;
$border-radius: 0px;

.#{$grommet-namespace}button {
  letter-spacing: 0.04167em;
}
@import 'grommet/scss/grommet-core/index.scss';

You can see that there are a lot of conventions here to work around the global aspects of SASS. For example, we add grommetux- as a prefix to all our components. Similarly $button prefix for all the variables that are used inside Button styles.

Using styled-components just felt right.

You can see this code in action inside the NEXT branch. Also, next-sample is a sample app using this new architecture. We don't yet have a lot of components, but it helps you to see what is coming.

What is going to break?

We will be removing components that have too much abstraction; the list currently includes Article, Card, Columns, Hero, LoginForm, Quote, Section, SocialShare, and Timestamp.

These components will either move to grommet-addons or be available as a codepen template. This will fix the pain point number 5.

We will also remove all deprecated props. If you are already using 1.5.0 and you don't see any deprecation warnings you are in good shape. There will be more deprecated props coming soon. For example, we will deprecate onClick for most of our components. The recommendation is to wrap the clickable element in a Grommet Button or Anchor. We will document this in release 2.0.

To have better support for tree-shaking, we will refactor the exports. Now every component has its folder, and we support styled-import without impacting the bundle size. You just need to use the babel-plugin-grommet. This fixes pain point number 7.

From

import Button from 'grommet/components/Button';

to

import { Button } from 'grommet';
// or
import Button from 'grommet/components/button';

FYI, our new build and package.json have support for module entry where we don't convert es6 to commonjs modules. This is supposed to have better support for tree shaking feature in module bundlers. Grommet 2.0 will support tree-shaking.

Apart from that, we don't foresee anymore breaking changes. We are expecting the transition to be very smooth. And to fix pain point number 8, we will be using codepen (or an equivalent) even more in the new documentation for Grommet 2.0, stay tuned 😄.

When?

Good news! The work has already started, we have around 60 cards published in our Waffle board. You can track progress on what is added and what is missing. We don't have a projected date yet, but we are hoping to have an alpha version out in the next month or so.

You can use Grommet NEXT today if you want, but the component set is limited, and we are still testing things out. To use it change your package.json to point to the NEXT-stable branch:

{
   "grommet": "https://github.com/grommet/grommet/tarball/NEXT-stable",
}
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.