Introducing Amplify UI's React Components

aspittel

Ali Spittel

Posted on July 7, 2022

Introducing Amplify UI's React Components

June 27, 2024: This blog post uses Amplify Gen 1, if you're starting a new Amplify app I recommend trying out Gen 2!

This week, my team at AWS launched React UI components which are really fun to build with - I want to show you all some of what you can create!

AWS Amplify UI is a set of primitive and cloud-connected components that enable customization, themability, and accessibility. There are primitive components for creating layouts, buttons, headers, ratings, and more. There are also components that connect to AWS resources to display maps and build authentication flows. Let's build a mapping application to work with the UI library!

Completed app with header, cards, and map

Start an App

First, create an application - I used Next.js but you could just as easily use Create React App.



npx create-next-app amplify-ui-demo
cd amplify-ui-demo


Enter fullscreen mode Exit fullscreen mode

Then, install the Amplify libraries and UI components:



npm i aws-amplify @aws-amplify/ui-react


Enter fullscreen mode Exit fullscreen mode

Amplify UI doesn't come with a font by default, so you can choose one you like. The default theme uses the Inter font - we'll install that in our app as well.



npm install @fontsource/inter


Enter fullscreen mode Exit fullscreen mode

At the top level of your application in /pages/_app.js, import the Amplify CSS file and inter font:



import "@aws-amplify/ui-react/styles.css";
import "@fontsource/inter/variable.css";


Enter fullscreen mode Exit fullscreen mode

Build a Basic UI

Now, let's build out our app's basic UI! We'll do this in our app's home page - /pages/index.js. I'll first create an array of restaurants above my React component. Each one will have a name, cuisine, rating, price, and a (randomly generated) latitude and longitude:



const restaurants = [
  {
    name: "Mannys's Burgers",
    cuisine: "American",
    rating: 5,
    price: "$$",
    location: {
      lat: "32.385348495775",
      long: "-85.738272191934",
    },
  },
  {
    name: "Mac n Cheesy",
    cuisine: "American",
    rating: 4,
    price: "$",
    location: {
      lat: "40.385358710927",
      long: "-78.637760520167",
    },
  },
  {
    name: "Giuliano's Italian Restaurant",
    cuisine: "Italian",
    rating: 5,
    price: "$$$",
    location: {
      lat: "35.396328108119",
      long: "-87.786869702867",
    },
  },
  {
    name: "The Pink Sheep",
    cuisine: "Fine Dining",
    rating: null,
    price: "$$$$",
    rating: 3,
    location: {
      lat: "45.386348035105",
      long: "-97.535870048241",
    },
  },
];


Enter fullscreen mode Exit fullscreen mode

I'll also pre-emptively import all the UI components I'll need. I'll also import the Next.js Link component.



import {
  withAuthenticator,
  Card,
  Badge,
  Heading,
  Rating,
  Text,
  Link,
  Flex,
  View,
  SearchField,
  useTheme,
  MapView,
} from "@aws-amplify/ui-react";

import NextLink from "next/link";


Enter fullscreen mode Exit fullscreen mode

We'll start off by a View component which will will render as a div by default. We'll keep the Next.js Head with a title tag in it.



function Home() {
  return (
    <View>
      <Head>
        <title>RestaurantList</title>
      </Head>
    </View>
  );
}


Enter fullscreen mode Exit fullscreen mode

Below the Head, let's build a header. We'll first use the View component again, but this time we'll render it as a header element instead of as a div. We'll also add some padding. Then we'll use the Flex component for flexbox. You can use props that mirror the flexbox CSS properties! We'll center the content within the row and add space around the items. We'll create another Flex and add some Links. We'll also add a heading with a level of 1 with the name of the site. Finally, we'll add another Flex with a SearchField inside of it.



<View as="header" padding="10px">
  <Flex direction="row" justifyContent="space-around" alignItems="center">
    <Flex>
      <NextLink href="">
        <Link>Home</Link>
      </NextLink>
      <NextLink href="/about">
        <Link>About</Link>
      </NextLink>
      <NextLink href="/shop">
        <Link>Shop</Link>
      </NextLink>{" "}
    </Flex>
    <Heading level={1} textAlign="center">
      RestaurantList
    </Heading>
    <Flex>
      <SearchField />
    </Flex>
  </Flex>
</View>


Enter fullscreen mode Exit fullscreen mode

After that, let's loop through our restaurants and add Cards for each. We'll create a Flex here so that we can display a map next to the cards in the future. Then we'll add a View component with a maxWidth set. We'll loop through the restaurants and create a Card for each. Each Card will have information about the Restaurant on the left side, and then a rating on the right. The Rating component will render the star rating for each restaurant!



<Flex>
  <View maxWidth="800px">
    {restaurants.map((restaurant) => (
      <Card variation="elevated" key={restaurant.name} margin="10px">
        <Flex direction="row" justifyContent="space-between">
          <Flex direction="column">
            <Heading level={3}>{restaurant.name}</Heading>
            <Badge size="large" variation="info" width="fit-content">
              {restaurant.cuisine}
            </Badge>
            <Text color="grey">{restaurant.price}</Text>
          </Flex>
          <Flex direction="column">
            <Rating value={restaurant.rating} maxValue={5} />
          </Flex>
        </Flex>
      </Card>
    ))}
  </View>
</Flex>


Enter fullscreen mode Exit fullscreen mode

Now your UI should look like this:

UI with header and cards on left side

Theming

Amplify UI is fully themeable -- you can make it so the components fully match your brand or style. There are some example themes used within the Amplify UI docs that totally change how the UI looks!

In this case, I'll change up some of the colors used. I'll use green as the primary theme color and yellow as the secondary. I'll add the theme object to the _app.js file. Amplify UI has colors builtin which is where the green and yellow are coming from, but you could also set these values to completely custom colors.



const earthyTheme = {
  name: "earthTheme",
  tokens: {
    colors: {
      brand: {
        primary: {
          10: { value: "{colors.green.10}" },
          20: { value: "{colors.green.20}" },
          40: { value: "{colors.green.40}" },
          60: { value: "{colors.green.60}" },
          80: { value: "{colors.green.80}" },
          90: { value: "{colors.green.90}" },
          100: { value: "{colors.green.100}" },
        },
        secondary: {
          10: { value: "{colors.yellow.10}" },
          20: { value: "{colors.yellow.20}" },
          40: { value: "{colors.yellow.40}" },
          60: { value: "{colors.yellow.60}" },
          80: { value: "{colors.yellow.80}" },
          90: { value: "{colors.yellow.90}" },
          100: { value: "{colors.yellow.100}" },
        },
      },
    },
  },
};


Enter fullscreen mode Exit fullscreen mode

To use the theme, import the ThemeProvider component.



import { ThemeProvider } from "@aws-amplify/ui-react";


Enter fullscreen mode Exit fullscreen mode

Then, wrap the top-level application component in the ThemeProvider and pass the theme prop set to the theme object.



function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider theme={earthyTheme}>
      <Component {...pageProps} />
    </ThemeProvider>
  );
}


Enter fullscreen mode Exit fullscreen mode

Using Themes in Components

You can also use attributes from themes directly within your components in order to style them. Inside the Home component in index.js, use the useTheme hook.



const { tokens } = useTheme();


Enter fullscreen mode Exit fullscreen mode

Then, let's set the background color of the header to the primary color from the theme:



<View as="header" padding="10px" backgroundColor={tokens.colors.brand.primary[40]}>


Enter fullscreen mode Exit fullscreen mode

If the primary brand color changes in the future, the header will update to match!

Cloud Connected Components

Amplify UI also offers cloud connected components so that you can connect to AWS services directly from React components. First, install the Amplify CLI. If it's your first time using Amplify, you'll need to configure it as well.



npm install -g @aws-amplify/cli


Enter fullscreen mode Exit fullscreen mode

Then, initialize Amplify within your project:



amplify init


Enter fullscreen mode Exit fullscreen mode

When prompted, choose a name for your project and then respond "Yes" to initialize with the defaults. Choose your AWS Profile as well.

Now, add authentication to your project by running:



amplify add auth


Enter fullscreen mode Exit fullscreen mode

Press enter for the default configuration, then choose Username and "No, I am done".

Then add mapping to your app:



amplify add geo


Enter fullscreen mode Exit fullscreen mode

Answer the questions as follows (though choose any name for the map):



? Select which capability you want to add: Map (visualize the geospatial data)
✔ Provide a name for the Map: · map53122572
✔ Who can access this Map? · Authorized and Guest users
Available advanced settings:
- Map style & Map data provider (default: Streets provided by Esri)

✔ Do you want to configure advanced settings? (y/N) · no


Enter fullscreen mode Exit fullscreen mode

Run amplify push to deploy your resources.

You'll then need to configure Amplify within your application code. Inside the ./pages/_app.js file add the following:



import awsExports from "../src/aws-exports";
import { Amplify } from "aws-amplify";

Amplify.configure(awsExports);


Enter fullscreen mode Exit fullscreen mode

Let's first add a map component to the app. Inside the Flex and under the close of the </View> for the restaurant cards, let's add a MapView. The latitude and longitude are for the United States, you may want to play around with the zoom level.



<MapView
  initialViewState={{
    latitude: "37.0902",
    longitude: "-95.7129",
    zoom: 4,
  }}
></MapView>


Enter fullscreen mode Exit fullscreen mode

Let's also add markers for each of our restaurants. We'll use react-map-gl for these.

Install the package:



npm i react-map-gl


Enter fullscreen mode Exit fullscreen mode

Import the markers:



import { Marker } from "react-map-gl";


Enter fullscreen mode Exit fullscreen mode

Then, inside the MapView tags, render the Markers.



{
  restaurants.map((restaurant) => (
    <Marker
      key={restaurant.name}
      latitude={restaurant.location.lat}
      longitude={restaurant.location.long}
    />
  ));
}


Enter fullscreen mode Exit fullscreen mode

Now you'll have a map!

Map of US with markers for restaurants

Now let's add an authentication flow so users need to sign in to view the map. Wrap the Home component in the higher-order withAuthenticator component. Now you'll be prompted to create a user and sign in!



export default withAuthenticator(Home);


Enter fullscreen mode Exit fullscreen mode

Authentication flow

You could also use database data instead of a JavaScript object by using Amplify's data categories.

Studio

You can also use Amplify Studio to go from Figma designs to cloud-connected code. Under the hood, the generated components will all use Amplify UI. Check out this tutorial to learn how to build a similar application using that workflow.

Conclusion

In this tutorial, we built a UI with both primitive and cloud-connected Amplify UI components. If you'd like to disconnect your app from the cloud and delete the authentication and geo resources, run amplify delete. As you build with Amplify UI, we'd love to hear your feedback!

💖 💪 🙅 🚩
aspittel
Ali Spittel

Posted on July 7, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

What was your win this week?
weeklyretro What was your win this week?

November 29, 2024

Where GitOps Meets ClickOps
devops Where GitOps Meets ClickOps

November 29, 2024

How to Use KitOps with MLflow
beginners How to Use KitOps with MLflow

November 29, 2024

Modern C++ for LeetCode 🧑‍💻🚀
leetcode Modern C++ for LeetCode 🧑‍💻🚀

November 29, 2024