• Stars
    star
    322
  • Rank 130,398 (Top 3 %)
  • Language
    JavaScript
  • License
    Apache License 2.0
  • Created about 6 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A tutorial to show how to use Grommet with create-react-app.

Grommet Starter - New App

Welcome ๐ŸŽ‰! Thanks for your interest in starting fresh with Grommet, we are thrilled to have you on board.

Deploy preview of the finished app.

Prerequisites

This tutorial assumes that you have node.js and a package manager; either npm (npm is installed with node.js) or yarn package manager. Create react app can be installed globally or locally using npx (npx comes with npm 5.2+).

Node Download Page - The latest LTS version will have node.js, npm, and npx.
Create React App Local Install - Instructions to install it locally can be found here (npm versions 5.2+).
Create React App Global Install - Not Recommended - Instructions to install it globally can be found here (npm versions 5.1 or earlier).
Yarn Package Manager - Not Required.

Getting Started

We are going to leverage and install the awesome create-react-app. We will call it CRA from now on.

npx create-react-app my-app
cd my-app

CRA will automatically install dependencies for you. It uses Yarn as a package manager behind the scenes. If you prefer to use NPM for your package management, you can delete the yarn.lock file and run npm install manually.

rm -rf yarn.lock
rm -rf node_modules
npm install

Start the development server.

npm start

Or if you are using yarn:

yarn start

You should see the CRA landing page. They keep updating it, but it will look something like this:

CRA Screenshot

Cleaning Up

We like a clean house. Let's first remove the modules and components we are not going to be using for this exercise.

Remove these files from the 'src' directory:

  • src/App.css
  • src/App.test.js
  • src/index.css
  • src/logo.svg

Inside src/index.js, remove the import of index.css.

import ReactDOM from 'react-dom/client';
- import './index.css';
import App from './App';

Inside src/App.js, remove the logo and the import of app.css

- import logo from './logo.svg';
- import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
-        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

You should see a beautiful, mostly black and white (accessible), landing page ๐Ÿ˜„.

src/App.js is the only module in this example (to keep things simple). All the steps from here on will just assume you are inside src/App.js.

Adding Grommet

To add grommet you first need to install our packages

npm install grommet grommet-icons styled-components --save

Or if you are using yarn:

yarn add grommet grommet-icons styled-components --save

You can now add the import of the Grommet component to the App.js file.

+ import { Grommet } from 'grommet';

Typically, you should include Grommet only once as one of your top-level nodes.

Let's replace the main div with Grommet.

- <div className="App">
+ <Grommet full>
  <header className="App-header">
    <p>
      Edit <code>src/App.js</code> and save to reload.
    </p>
    <a
      className="App-link"
      href="https://reactjs.org"
      target="_blank"
      rel="noopener noreferrer"
    >
      Learn React
    </a>
  </header>
+ </Grommet>
- </div>

You will notice no visible change resulted from including Grommet. Everything in Grommet is self-contained with very minimal global settings.

You might be asking, 'Why do you include it if nothing is changing?' The answer is simple: Although not strictly required, we recommend you add Grommet from day one, so that you can customize it in the future by using a theme.

Let's now and add a custom font-family, font-size, and line-height.

Below the import statements, let's add an initial theme declaration:

const theme = {
  global: {
    font: {
      family: "Roboto",
      size: "18px",
      height: "20px",
    },
  },
};

And modify the Grommet tag with our new theme:

<Grommet theme={theme} full>

This theme will propagate to all components under this given Grommet instance.

FYI. To access Roboto you need to include the font-face. Let's update public/index.html to include the font and fix some browser defaults.

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
+   <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" />
    <title>React App</title>
+   <style type="text/css">
+     body {
+       margin: 0;
+     }
+   </style>
  </head>

Look at your updated landing page, and you should see that the font-size and font-family are properly applied.

Good job, you just completed an important step in your Grommet journey.

Understanding Box

Box is an abstraction over Flexbox, and it is very likely you will be using it very frequently in your Grommet app.

Box is the main building block container for Grommet. There are also Grommet components that in essence are just Box components with a few initial props defined. For example the Header, Footer, and Card components are built using Box and can accept any props that Box can. The benefit of using components like Header and Footer is Grommet takes care of some of the work for you by pre-defining some props.

To start off we are going to use the Header and Text components in our app. Let's go the the App.js file and import them:

- import { Grommet } from 'grommet';
+ import { Grommet, Header, Text } from 'grommet';

We like to keep our imports in alphabetical order ๐Ÿ˜„.

Let's create an AppBar component and replace the header tag with it.

+const AppBar = (props) => (
+ <Header
+   background="brand"
+   pad={{ left: "medium", right: "small", vertical: "small" }}
+   elevation="medium"
+   {...props}
+ />
+);

const App = () => {
  return (
    <Grommet theme={theme}>
-     <header className="App-header">
-       <p>
-         Edit <code>src/App.js</code> and save to reload.
-       </p>
-       <a
-         className="App-link"
-         href="https://reactjs.org"
-         target="_blank"
-         rel="noopener noreferrer"
-       >
-         Learn React
-       </a>
-     </header>
+     <AppBar>
+       <Text size="large">My App</Text>
+     </AppBar>
    </Grommet>
  );
}

AppBar is just a Box with row direction. Children are justified between (a space will be added in between them). We add an elevation to simulate the same box-shadow from the original example.

Look at your browser again. You should see the AppBar with the brand background and some elevation.

With Grommet it is very easy to apply custom brand colors. The place to change colors is in the theme object as you might have already guessed.

const theme = {
  global: {
+   colors: {
+     brand: '#228BE6',
+   },
    font: {
      family: 'Roboto',
      size: '18px',
      height: '20px',
    },
  },
};

The AppBar now has a different color. You can create colors with any name; brand was just an example. Another great Grommet feature is the ability to easily declare context-aware colors which automatically adapt to light and dark themes. That is, any color can have two variations: dark and light. For example, use a light text color in a dark background, and vice-versa. We have created this codesandbox with more details on color usage.

For more information on the theme checkout the theme wiki page.

Adding Page, PageContent, and PageHeader

Now that we have an AppBar setup let's add the Page, PageContent, and PageHeader components into our App.

- import { Grommet, Header, Text } from 'grommet';
+ import { Grommet, Header, Page, PageContent, PageHeader, Text } from 'grommet';
<Grommet theme={theme} full>
+ <Page>
    <AppBar>
      <Text size="large">My App</Text>
    </AppBar>
+   <PageContent>
+     <PageHeader title="Welcome to Grommet!" />
+   </PageContent>
+ </Page>
</Grommet>

Page is a helpful container for providing consistent layout across pages in an application. Page and PageContent work together to ensure horizontal alignment, max-width, and responsive behaviors are applied in a consistent, turnkey manner.

Notice that the AppBar is not a child of PageContent. This allows the AppBar to stretch across the full width of the screen without being constrained by the max-width of the PageContent.

Adding React State

Everything is so static here. Let's add some state. We are going to add a button to the AppBar to switch between light and dark modes.

We need to import useState from React and grab some icons from the grommet-icons library.

- import React from "react";
+ import React, { useState } from "react";
- import { Grommet, Header, Page, PageContent, PageHeader, Text } from 'grommet';
+ import {
+   Button,
+   Grommet,
+   Header,
+   Page,
+   PageContent,
+   PageHeader,
+   Text,
+ } from "grommet";
+ import { Moon, Sun } from "grommet-icons";

Let's make this a little easier to read for you and your future co-workers by breaking the long import statement down to one component per line. You may want to consider using prettier to auto format for you (Tip: you may want to change prettier config default to prettier.singleQuote: true).

const App = () => {
+ const [dark, setDark] = useState(false);
+
  return (
-   <Grommet theme={theme} full>
+   <Grommet theme={theme} full themeMode={dark ? "dark" : "light"}>
      <Page>
        <AppBar>
          <Text size="large">My App</Text>
+         <Button
+           a11yTitle={dark ? "Switch to Light Mode" : "Switch to Dark Mode"}
+           icon={dark ? <Moon /> : <Sun />}
+           onClick={() => setDark(!dark)}
+         />
        </AppBar>
...

We are just leveraging React state by creating a dark flag initially set to false. Once we click the theme mode toggle button, we toggle the dark state. The button then switches the theme between 'dark' and 'light'.

Notice that switching between light and dark mode isn't currently causing any changes. This is because our current theme doesn't have anything specified for dark mode. Lets merge our custom theme with the grommet theme so that we can see what a theme looks like when it is setup for dark mode.

First we need to import the deepMerge function that will allow us to combine two grommet themes. We will also need to import the grommet theme.

import {
  Button,
  Grommet,
+ grommet,
  Header,
  Page,
  PageContent,
  PageHeader,
  Text,
} from "grommet";
+ import { deepMerge } from "grommet/utils";

Now lets adjust our custom theme.

- const theme = {
+ const theme = deepMerge(grommet, {
  global: {
    colors: {
      brand: "#228BE6",
    },
    font: {
      family: "Roboto",
      size: "14px",
      height: "20px",
    },
  },
+ });
- };

Now when we toggle our dark and light button we should see some changes.

Add Tip

The purpose of our light/dark toggle button may not be obvious just from the icons. Let's add a Tip to the Button that gives some additional guidance.

import {
+ Box,
  Button,
  Grommet,
  grommet,
  Header,
  Page,
  PageContent,
  PageHeader,
  Text,
} from "grommet";
<Button
  a11yTitle={dark ? "Switch to Light Mode" : "Switch to Dark Mode"}
  icon={dark ? <Moon /> : <Sun />}
  onClick={() => setDark(!dark)}
+  tip={{
+    content: (
+      <Box
+        pad="small"
+        round="small"
+        background={dark ? "dark-1" : "light-3"}
+      >
+        {dark ? "Switch to Light Mode" : "Switch to Dark Mode"}
+      </Box>
+    ),
+    plain: true,
+  }}
/>

Now when we hover over the Button it will give us more info on what the Button does.

Add Grid and Cards

Let's add some more content to our App. We will need to add the following components:

import {
  Box,
  Button,
+ Card,
+ CardHeader,
+ CardBody,
+ CardFooter,
+ Grid,
  Grommet,
  grommet,
  Header,
+ Heading,
  Page,
  PageContent,
  PageHeader,
+ Paragraph,
  Text,
} from "grommet";

Let's create a CardTemplate component.

+ const CardTemplate = ({ title }) => {
+   return (
+     <Card>
+       <CardHeader pad="medium">
+         <Heading level={2} margin="none">
+           {title}
+         </Heading>
+       </CardHeader>
+       <CardBody pad="medium">
+         <Paragraph>
+           Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
+           porttitor non nulla ac vehicula. Aliquam erat volutpat. Mauris auctor
+           faucibus est at mattis. Aliquam a enim ac nisi aliquam consectetur et
+           ac velit. Mauris ut imperdiet libero.
+         </Paragraph>
+       </CardBody>
+       <CardFooter pad="medium" background="background-contrast">
+         Footer
+       </CardFooter>
+     </Card>
+   );
+ };

Now let's add some cards to the PageContent within the App.

<PageContent>
  <PageHeader title="Welcome to Grommet!" />
+ <CardTemplate title={"Card 1"} />
+ <CardTemplate title={"Card 2"} />
+ <CardTemplate title={"Card 3"} />
</PageContent>

Our App now contains some Cards but they looks a little strange stretching across the entire Page. Let's organize our Cards within a Grid.

<PageContent>
  <PageHeader title="Welcome to Grommet!" />
+ <Grid columns="medium" gap="large" pad={{ bottom: "large" }}>
    <CardTemplate title={"Card 1"} />
    <CardTemplate title={"Card 2"} />
    <CardTemplate title={"Card 3"} />
+ </Grid>
</PageContent>

Now that are Cards are contained within a Grid, they sit nicely side by side.

Making it responsive

If you adjust the size of the browser window, not ice that Grommet is taking care of a lot of the responsive behavior for us.

On a small screen (around the size of most mobile devices) the content within the cards gets to be a bit long. Let's change the text content in the c=Cards so that it truncates after 3 lines when we are in a small viewport.

First we need to import ResponsiveContext.

import {
  Box,
  Button,
  Card,
  CardHeader,
  CardBody,
  CardFooter,
  Grid,
  Grommet,
  grommet,
  Header,
  Heading,
  Page,
  PageContent,
  PageHeader,
  Paragraph,
+ ResponsiveContext,
  Text,
} from "grommet";

Now let's change CardTemplate to use ResponsiveContext. ResponsiveContext uses react context api behind the scenes.

const CardTemplate = ({ title }) => {
+ const size = useContext(ResponsiveContext);
  return (
    <Card>
      <CardHeader pad="medium">
        <Heading level={2} margin="none">
          {title}
        </Heading>
      </CardHeader>
      <CardBody pad="medium">
-       <Paragraph>
+       <Paragraph maxLines={size === "small" ? 3 : undefined}>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
          porttitor non nulla ac vehicula. Aliquam erat volutpat. Mauris auctor
          faucibus est at mattis. Aliquam a enim ac nisi aliquam consectetur et
          ac velit. Mauris ut imperdiet libero.
        </Paragraph>
      </CardBody>
      <CardFooter pad="medium" background="background-contrast">
        Footer
      </CardFooter>
    </Card>
  );
};

Now when you view the page with a narrow viewport the Paragraph content in the Cards will be truncated at 3 lines.

Well, let's celebrate because now we have a responsive Grommet app, thanks for hanging with us until now.

Final Considerations

We will keep updating this starter page with more steps. The latest completed version of this exercise is available in this repo in the master branch.

Grommet can co-exist with other frameworks. We will never add global styles that will affect your existing components. Although the reverse is not true. By helping other teams migrate to Grommet, we have identified a common problem: global CSS modifiers affecting Grommet components. Whenever you see something weird, try to reproduce it outside your application environment.

If you are able to reproduce it, be nice, file an issue. If you cannot reproduce it, inspect your elements, and you will probably find some global CSS applying unexpected overly opinionated changes to our components. As always, you can join our Slack and share your pain with us.

Finally, here are some additional pointers to keep you engaged:

  1. Using Grommet in an existing app tutorial
  2. Grommet Storybook - a lot of examples on how to use our components. Most of them are not real app scenarios though. They are there to illustrate our different props.
  3. Grommet Sandbox - more friendly when you want to edit and play with the examples, also does not have real app scenarios.
  4. Grommet Site - resources and documentation for Grommet components can be found here.
  5. Grommet Slack Inviter - don't forget to join our awesome community!

More Repositories

1

grommet

a react-based framework that provides accessibility, modularity, responsiveness, and theming in a tidy package
JavaScript
8,320
star
2

grommet-icons

Iconography for Grommet and React.js
JavaScript
334
star
3

design-kit

Grommet Design Kit
294
star
4

jsx-to-string

Parse your React JSX component to string
JavaScript
123
star
5

grommet-ferret

Example application using grommet
JavaScript
119
star
6

grommet-design

Grommet design resources, including design sticker sheets, application templates, and icons.
109
star
7

grommet-starter-existing-app

A tutorial to show how to plug Grommet in an existing app.
JavaScript
82
star
8

grommet-standalone

Sample app using Grommet without the development stack.
JavaScript
78
star
9

hpe-design-system

HPE Design System
JavaScript
48
star
10

grommet-designer

JavaScript
36
star
11

grommet-site

Site for Grommet v2
JavaScript
32
star
12

grommet-docs

Website project for Grommet framework (http://grommet.io)
JavaScript
30
star
13

grommet-people-finder

People finder app that uses LDAP server to look for users, groups and locations.
JavaScript
30
star
14

grommet-cms

Grommet CMS - A content management system with world class UX
JavaScript
30
star
15

grommet-cli

Deprecated, use create-react-app for v2 instead. Command Line interface for grommet
JavaScript
28
star
16

html-jsx-loader

DEPRECATED: html loader module to convert HTML to JSX for webpack
JavaScript
26
star
17

grommet-theme-hpe

Hewlett Packard Enterprise grommet theme
JavaScript
23
star
18

react-desc

Add a schema to your React components based on React PropTypes
JavaScript
21
star
19

grommet-react-app

Integration of Grommet with create-react-app
JavaScript
20
star
20

grommet-addons

Higher order components and utilities based on core grommet components.
JavaScript
17
star
21

grommet-toolbox

[DEPRECATED] Developer Environment for Grommet applications
JavaScript
13
star
22

grommet-infographic

Grommet Infographic Template
JavaScript
12
star
23

grommet-cms-boilerplate

Grommet CMS Boilerplate
JavaScript
12
star
24

micro-frontend

A proof of concept for using React + Grommet in a micro frontend architecture.
JavaScript
12
star
25

grommet-vending

JavaScript
12
star
26

grommet-theme-designer

JavaScript
11
star
27

github-org-stats

Gather statistics for your github organization
JavaScript
11
star
28

nextjs-boilerplate

A boilerplate for using Next.js Framework, React library and the Grommet Component Library.
JavaScript
10
star
29

grommet-index

UI and example server for searching, filtering, and displaying mass quantities of items.
JavaScript
10
star
30

grommet-sample

Sample app of migrating Grommet v1 to v2
JavaScript
8
star
31

react-formify

[DEPRECATED] An uncontrolled react Form component with validation capabilities.
JavaScript
8
star
32

grommet-drone-ui

Grommet UI for Drone CI
JavaScript
7
star
33

grommet-swagger

Swagger API browser built using grommet
JavaScript
7
star
34

grommet-sub-page

Grommet Sub Page Template
JavaScript
6
star
35

grommet-cms-content-blocks

Content blocks for the grommet-cms
JavaScript
5
star
36

grommet-icons-site

Website for grommet-icons library
JavaScript
5
star
37

grommet-templates

Higher order abstraction composite components built from Grommet core components.
JavaScript
5
star
38

grommet-sandbox

Grommet component samples for use with CodeSandbox
JavaScript
5
star
39

grommet-todo

Todo application created on top of Grommet framework
JavaScript
5
star
40

grommet-vertical-narrative

Grommet Vertical Narrative Infographic Template
JavaScript
5
star
41

babel-plugin-grommet

Babel plugin to transform member style imports into default imports
JavaScript
4
star
42

grommet-primary-page

Grommet Primary Page Template
JavaScript
4
star
43

v2-launch-slides

Grommet version 2 launch party slides
TypeScript
4
star
44

grommet-tabular

An exploration of interacting with data in different ways.
JavaScript
4
star
45

grommet-tv

A TV interface prototype built with grommet
JavaScript
4
star
46

next-sample

Sample app using Grommet 2.0
JavaScript
4
star
47

grommet-v1

A mapping of v1 component signatures to v2 implementations
JavaScript
4
star
48

grommet-presentation

A library with a set of components to make presentations on top of Grommet UX framework
JavaScript
4
star
49

grommet-slides

Grommet based slide viewer.
TypeScript
3
star
50

grommet-blog

An oddly simple blog implementation
JavaScript
3
star
51

grommet-details-page

Grommet Details Page Template
JavaScript
3
star
52

grommet-tools

A website for Grommet No-Code tools
JavaScript
2
star
53

image-library

Sample App used for training
PostScript
2
star
54

csun2016

Presentation for CSUN 2016
JavaScript
2
star
55

slide

JavaScript
2
star
56

grommet-bower

Bower distribution of Grommet
JavaScript
2
star
57

grommet-styles

Independent styles for Grommet apps
JavaScript
2
star
58

grommet-publisher

build documentation
JavaScript
2
star
59

hpe-design-tokens

CSS
2
star
60

grommet-interns-onboard

A hub to onboard the interns of 2021
JavaScript
2
star
61

grommet-simple

Minimalist project without the entire dev stack
JavaScript
2
star
62

grommet-theme-hp

HP Inc. grommet theme
JavaScript
2
star
63

grommet-theme-dxc

DXC Technologies grommet theme
JavaScript
1
star
64

grommet-leaflet

Example of using leafletjs.org maps with react and grommet
JavaScript
1
star
65

grommet-chat

JavaScript
1
star
66

grommet-exp

TypeScript
1
star
67

grommet-theme-nineties

1990s theme
JavaScript
1
star
68

grommet-ldap-server

A node-only ldap server for Grommet people finder
JavaScript
1
star
69

grommet-vagrant

A vagrant box to make developing with grommet easier.
Shell
1
star
70

grommet-images

JavaScript
1
star
71

grommet-exp-vite

TypeScript
1
star
72

grommet-email

Produce grommet styled HTML for use in email contexts.
JavaScript
1
star
73

grommet-passport

A Grommet based login utility for HPE Passport.
JavaScript
1
star
74

grommet-exp-theme

TypeScript
1
star
75

grommet-weather

Simple weather app using Grommet.
JavaScript
1
star
76

grommet-stats-site

DataViz showcase for grommet-org-stats
JavaScript
1
star