React

Version: 3.0.6

Applying visual style for the Unifi React library comes in two flavors: theming and component styling. Theming refers to the base, global styles that affect all instances of a component, as well as typography and color palette variables. Styling refers to downstream customization of a component's instance when the desired effect is not available via component props to change the variant.

Extend the theme to:

  • Update the primary, secondary, or error colors;
  • Change the font or typographic scale;
  • Globally update something about a specific component's root or one of it's states, ex. background color on hover of primary contained buttons.

Use styling to:

  • Adjust relational spacing;
  • Improve contrast for accessibility;
  • When creating your own component or composition.

Unifi’s React library offers JSS and supporting functions as the mechanism for styling components. Products can update their custom theme, and style components, in the form of a JavaScript object. This makes dynamic generation, such as via the Velocity microservice foundation, style-bloat free. It also assists in maintaining consistency across naming conventions.

React Theming

The Unifi Theme ships with the React component library, but there are a few steps to ensure it's loaded.

Essential Theme Functions

For this method:

  1. Import the required functions as shown in the sample;
  2. Create a theme constant set to createTheme() to use default Unifi (see Theme Customization for custom themes);
  3. Supply the theme to UnifiThemeProvider, which will then make the theme available down the React tree thanks to React context.
  4. Apply at the highest level of your app, wrapping your main app component.

Note: The following method is appropriate for non-SSR and learning Unifi, such as inclusion in Create React App. For SSR, these functions are still used but also extended.

Functions for SSR

Handling the Server Side Request

The following example uses express, but the important part within your architecture is that something similar to the handleRender function is called for each server request.

The first thing that we need to do on every request is to create a new ServerStyleSheets.

When rendering, we will wrap App, our root component, inside a StylesProvider and UnifiThemeProvider to make the style configuration and the theme available to all components in the component tree.

The key step in server-side rendering is to render the initial HTML of our component before we send it to the client-side. To do this, we use ReactDOMServer.renderToString().

We then get the CSS from our sheets using sheets.toString(). We will see how this is passed along in our renderFullPage function.

Handling the Client Side

The client-side is straightforward. All we need to do is remove the server-side generated CSS. Let's take a look at our client file:

Theme Customization

Due to the use of JSS, the theme declaration is provided as a JavaScript object.

The most basic way to extend from Unifi is with the following declaration, which will update the palette's primary and secondary colors.

The demo also shows the use of the built-in darken function, but you may include a known hex or rgba value instead. lighten is also available, and both work like their SCSS complements.

Customized Typography

Here is the full range of typography values you can customize. Each definition accepts any additional CSS you need.

Note: Demo shows updating the primary font to Roboto, but for performance reasons, we are not loading it so the demo may or may not be rendering as Roboto.

If you are looking to update the Typography component, see Theme Overrides.

Component Styling

As we mentioned at the start of this guide, Unifi’s React library offers JSS and supporting functions as the mechanism for styling components. In the previous section, JSS functions were used directly to provide SSR support. However, the essential functions necessary for using JSS syntax are baked into the Unifi library as custom extensions.

There are two ways to provide styling, depending on need:

  1. Globally via theme overrides if the intent is to impact all instances;
  2. Per instance of a component, also used for new components.

CSS Classes

All the components accept a classes property to customize the styles. The classes design answers two constraints: to make the classes structure as simple as possible while sufficient to implement the Unifi specification.

You can find a list of available classes per component within the "Properties" section of each demo page.

Whether you are modifying globally in the theme or on an instance, these same rules apply.

  • The class applied to the root element is always called root;
  • All the default styles are grouped in a single class;
  • The classes applied to non-root elements are prefixed with the name of the element, e.g. paperWidthXs in the Dialog component;
  • The variants applied by a boolean property aren't prefixed, e.g. the gutterBottom class applied by the gutterBottom property;
  • The variants applied by an enum property are prefixed, e.g. the colorPrimary class applied by the color="primary" property;
  • A variant has one level of specificity. The color and variant properties are considered a variant. The lower the style specificity is, the simpler it is to override.
  • We increase the specificity for a variant modifier. We already have to do it for the pseudo-classes (:hover, :focus, etc.). It allows much more control at the cost of more boilerplate. Hopefully, it's also more intuitive.

Theme Overrides

To promote consistency between components and manage the user interface appearance as a whole, you can take advantage of the overrides key of the theme.

Within your custom theme declaration, the overrides section can be loaded with one key per component, and any CSS you'd like, attached in the format shown in the CSS Classes section.

To determine what a component's key is, assume Mui[Component], ex. MuiButton, as well as Mui[Component]-[StyleRuleName]. You may also use your browser inspector when running a development build to see which classes are being applied to a given component to help choose the best candidate to update.

Style Component Instances

The following method of withStyles() (and for TypeScript the interface WithStyles) can be used for both Unifi components and to extend Unifi's use in your custom components and component compositions, ie. a Dashboard view.

The demo component showcases:

  • Importing necessary style functions (and TypeScript interfaces, if needed);
  • Using createStyles to create JSS-formatted custom styles;
  • Destructuring props from the Theme object: breakpoints, palette, shape, shadows, spacing;
  • Accessing sub-properties of Theme props;
  • Use of the breakpoints function;
  • Creating a modifying class for the Typography component and attaching it specifically as an override for the h1 variant via the classes prop;
  • Creating a custom class - customContainer - for a custom element, and adding via className