FED Parlez ! Épisode 2 :Thème de l'interface utilisateur matérielle

Dans l'épisode d'aujourd'hui, nous expliquerons comment implémenter le thème de vos applications à l'aide du fournisseur de thèmes de Material UI. Nous allons tout configurer depuis :

  • Typographie
  • Points d'arrêt
  • Couleurs
  • Boutons
  • Comment structurer votre application

Commençons !

Table des matières :

  • 🤔 Qu'est-ce qu'un thème ?
  • Configuration du thème
    • Configurer le thème
  • Typographie
    • Échelle de caractères
    • Dimensionnement de la police
  • Points d'arrêt
    • Configuration
    • Accéder aux points d'arrêt
    • Requêtes média CSS
    • Requêtes média JS
  • Palette de couleurs
    • Choisir vos couleurs
    • Appliquer la palette
  • Boutons
  • Échafaudez votre application
    • Barre d'applications
    • Contenu du corps
    • Navigation dans le menu principal
  • 🙏 Fermeture

🤔 Qu'est-ce qu'un thème ?

Les thèmes sont importants car ils définissent l'apparence de votre application globale. Un bon moteur de thème permettra à l'équipe de développement de configurer les choses une fois de manière centralisée, plutôt que de façon répétitive.

Le thème spécifie la couleur des composants, l'obscurité des surfaces, le niveau d'ombre, l'opacité appropriée des éléments d'encre, etc.

Les thèmes vous permettent d'appliquer un ton cohérent à votre application. Il vous permet de personnaliser tous les aspects de conception de votre projet afin de répondre aux besoins spécifiques de votre entreprise ou de votre marque.

Pour favoriser une plus grande cohérence entre les applications, des types de thèmes clairs et sombres sont disponibles au choix. Par défaut, les composants utilisent le type de thème clair.
(@material-ui)

Voici un bon exemple où la responsable de la conception de GitHub, Diana Mounter, parle en profondeur des difficultés qu'elle a rencontrées pour créer un thème sombre et où la création d'un thème centralisé plus tôt aurait rendu leur vie beaucoup plus facile.

Configuration du thème

La première chose à faire est d'envelopper votre application avec le ThemeProvider de MUI composant.

// src/app.tsx

import { CssBaseline, ThemeProvider } from '@material-ui/core';

export default function App() {
  return (
    <ThemeProvider> {/* Property 'theme' is missing... */}
      <CssBaseline />
      <h1>Design System</h1>
    </ThemeProvider>
  );
}

Ce qui précède encapsule maintenant chacun des composants enfants de votre application avec le fournisseur de thème, exposant ainsi votre thème via l'API de contexte de React, que nous apprendrons plus tard à utiliser.

Créons maintenant un nouveau dossier dans votre src répertoire appelé theme . C'est ici que nous pouvons stocker chacune de nos configurations de thème.

Créez le fichier suivant :

// src/theme/index.tsx

import { createMuiTheme } from '@material-ui/core';

export default createMuiTheme({

})

La sortie de createMuiTheme créera un Theme objet, que notre ThemeProvider nouvellement ajouté Composant d'ordre supérieur (HoC) requis. Branchons-le.

// src/app.tsx

import { CssBaseline, ThemeProvider } from '@material-ui/core';
import Theme from './theme';

export default function App() {
  return (
    <ThemeProvider theme={Theme}>
      <CssBaseline />
      <h1>Design System</h1>
    </ThemeProvider>
  );
}

Configurer le thème

L'un des avantages vraiment intéressants de l'utilisation de MUI est que leurs définitions TypeScript sont bien documentées. Ceci est évident en utilisant le "Go to definition" de VSCode sur n'importe lequel de leurs exports de module par exemple si nous avons plongé dans leur createMuiTheme composant, vous verrez quelque chose comme ceci :

// node_modules/@material-ui/core/styles/createMuiTheme.d.ts

import { Breakpoints, BreakpointsOptions } from './createBreakpoints';
import { Mixins, MixinsOptions } from './createMixins';
import { Palette, PaletteOptions } from './createPalette';
import { Typography, TypographyOptions } from './createTypography';
import { Shadows } from './shadows';
import { Shape, ShapeOptions } from './shape';
import { Spacing, SpacingOptions } from './createSpacing';
import { Transitions, TransitionsOptions } from './transitions';
import { ZIndex, ZIndexOptions } from './zIndex';
import { Overrides } from './overrides';
import { ComponentsProps } from './props';

export type Direction = 'ltr' | 'rtl';

export interface ThemeOptions {
  shape?: ShapeOptions;
  breakpoints?: BreakpointsOptions;
  direction?: Direction;
  mixins?: MixinsOptions;
  overrides?: Overrides;
  palette?: PaletteOptions;
  props?: ComponentsProps;
  shadows?: Shadows;
  spacing?: SpacingOptions;
  transitions?: TransitionsOptions;
  typography?: TypographyOptions | ((palette: Palette) => TypographyOptions);
  zIndex?: ZIndexOptions;
  unstable_strictMode?: boolean;
}

export interface Theme {
  shape: Shape;
  breakpoints: Breakpoints;
  direction: Direction;
  mixins: Mixins;
  overrides?: Overrides;
  palette: Palette;
  props?: ComponentsProps;
  shadows: Shadows;
  spacing: Spacing;
  transitions: Transitions;
  typography: Typography;
  zIndex: ZIndex;
  unstable_strictMode?: boolean;
}

export default function createMuiTheme(options?: ThemeOptions, ...args: object[]): Theme;

Nous savons maintenant comment nous connecter à ce module et remplir le ThemeOptions .

Typographie

Il est important d'utiliser la bonne typographie pour un support donné, que ce soit pour les appareils imprimés, numériques, basse/haute résolution.

Une typographie bien définie doit permettre à vos spectateurs de distinguer clairement le contenu et ses formalités. Par exemple, la taille de la police d'une balise H1 doit être visuellement plus grande que celle d'un H2, de même avec H2 vs H3 et ainsi de suite; c'est ce qu'on appelle la "mise à l'échelle des polices". En savoir plus sur le système de type.

Choisissons quelques polices à l'aide de Google Fonts, 1 en gras pour nos titres et une autre pour le reste de notre application.


Étape 1 :Trouvez la police d'en-tête souhaitée

Naviguez dans leur bibliothèque de polices jusqu'à ce que vous en trouviez une que vous aimez (je suis content de "Krona One"). Cliquez ensuite dans la case de la police pour naviguer et en savoir plus sur les détails de la police.


Étape 2 :Ajoutez la police à votre bac "Familles sélectionnées"

En procédant à la sélection de votre police, assurez-vous de cliquer sur "Sélectionner ce style" pour l'ajouter à votre plateau.


Étape 3 :Associez votre police à l'une de leurs suggestions

Une fonctionnalité intéressante fournie par Google Fonts est qu'ils vous donnent une liste d'associations suggestives pour la police que vous avez sélectionnée. Si aucun des appariements ne vous convient, revenez à la page d'accueil et trouvez une autre police. Une fois que vous êtes satisfait, assurez-vous de l'ajouter à votre plateau.


Étape 4 :Intégrez vos polices à votre application

Le plateau "Familles sélectionnées" vous permettra ensuite de revoir vos polices sélectionnées ainsi que de vous présenter comment les intégrer dans votre application. Dans ce cas, j'utiliserais leur proposition <link> implémentation principalement parce qu'ils fournissent le <link rek="preconnect"> ligne.

Copiez et collez leur extrait de code dans le <head> bloquer.

// public/index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="description" content="Web site created using create-react-app" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="msapplication-TileColor" content="#231f20">
  <meta name="theme-color" content="#231f20">
  <link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
  <link rel="manifest" href="/site.webmanifest">
  <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#40bfb4">
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Jura&family=Krona+One&display=swap" rel="stylesheet">
  <title>Design System | QuinTRON</title>
</head>

<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
</body>

</html>

Cela indique au navigateur de demander nos polices Google lors du chargement initial de l'application. Les polices elles-mêmes ne seront apparentes qu'une fois que nous aurons lié les familles de polices CSS à notre code HTML. Pour ce faire, nous devrons étendre notre thème en ajoutant une configuration Typographie.

Le composant Typography de MUI permet la configuration des variantes suivantes (j'ai ajouté leur mappage d'éléments HTML par défaut sous forme de commentaires en ligne) :

export type Variant =
  | 'h1'        // maps to <h1>
  | 'h2'        // maps to <h2>
  | 'h3'        // maps to <h3>
  | 'h4'        // maps to <h4>
  | 'h5'        // maps to <h5>
  | 'h6'        // maps to <h6>
  | 'subtitle1' // maps to <h6>
  | 'subtitle2' // maps to <h6>
  | 'body1'     // maps to <p>
  | 'body2'     // maps to <p>
  | 'caption'   // maps to <span>
  | 'button'    // maps to <button>
  | 'overline'; // maps to <span>

Vous pouvez également modifier les mappages HTML par défaut en implémentant l'exemple suivant :

// theme/index.tsx

const theme = createMuiTheme({
  props: {
    MuiTypography: {
      variantMapping: {
        body1: 'span', // traditionally set as <p>
        body2: 'span', // traditionally set as <p>
      }
    }
  }
});

Nous pouvons créer notre fichier Typographie pour configurer chacune des définitions de variantes.

// stc/theme/typography.tsx

import { TypographyOptions } from '@material-ui/core/styles/createTypography';

export const typography: TypographyOptions = {
  h1:         { fontFamily: "'Krona One', sans-serif" },
  h2:         { fontFamily: "'Krona One', sans-serif" },
  h3:         { fontFamily: "'Krona One', sans-serif" },
  h4:         { fontFamily: "'Krona One', sans-serif" },
  h5:         { fontFamily: "'Krona One', sans-serif" },
  h6:         { fontFamily: "'Krona One', sans-serif" },
  subtitle1:  { fontFamily: "'Jura', sans-serif" },
  subtitle2:  { fontFamily: "'Jura', sans-serif" },
  body1:      { fontFamily: "'Jura', sans-serif" },
  body2:      { fontFamily: "'Jura', sans-serif" },
  caption:    { fontFamily: "'Jura', sans-serif" },
  button:     { fontFamily: "'Jura', sans-serif" },
  overline:   { fontFamily: "'Jura', sans-serif" },
}

Ajoutez ensuite votre configuration Typographie au module Thème.

// src/theme/index.tsx

import { createMuiTheme } from '@material-ui/core';
import { typography } from './typography';

export default createMuiTheme({
  typography
})

Votre police Google est désormais liée aux composants MUI Typography ! Ajoutons du contenu à notre application et testons son apparence.

// src/app.tsx

import { CssBaseline, ThemeProvider } from '@material-ui/core';

import Theme from './theme';

export default function App() {
  return (
    <ThemeProvider theme={Theme}>
      <CssBaseline />
      <h1>Heading 1</h1>
      <h2>Heading 2</h2>
      <h3>Heading 3</h3>
      <h4>Heading 4</h4>
      <h5>Heading 5</h5>
      <h6>Heading 6</h6>
      <p>Body content</p>
      <button>Button label</button>
      <caption>Caption text</caption>
    </ThemeProvider>
  );
}

Voici à quoi ressemble :

🤔 Hm, je ne vois pas ma police d'en-tête. Ah-huh, c'est parce que j'utilisais les balises HTML par défaut, pas le composant Typography de MUI. Convertissons-les comme ceci :

// src/app.tsx

import { Button, CssBaseline, ThemeProvider, Typography } from '@material-ui/core';

import Theme from './theme';

export default function App() {
  return (
    <ThemeProvider theme={Theme}>
      <CssBaseline />
      <Typography variant="h1">Heading 1</Typography>
      <Typography variant="h2">Heading 2</Typography>
      <Typography variant="h3">Heading 3</Typography>
      <Typography variant="h4">Heading 4</Typography>
      <Typography variant="h5">Heading 5</Typography>
      <Typography variant="h6">Heading 6</Typography>
      <Typography variant="body1">Body content 1</Typography>
      <Typography variant="body2">Body content 2</Typography>
      <Typography variant="subtitle1">Subtitle 1</Typography>
      <Typography variant="subtitle2">Subtitle 2</Typography>
      <Typography variant="caption">Caption text</Typography>
      <Typography variant="overline">Overline text</Typography>
      <Button variant="contained">Button Contained</Button>
      <Button variant="outlined">Button Outlined</Button>
      <Button variant="text">Button Text</Button>
    </ThemeProvider>
  );
}

Voici à quoi ressemble maintenant :

❤️ Voilà à quoi devraient ressembler les polices !

Échelle des types

La prochaine étape évidente consiste à implémenter la mise à l'échelle des polices dans l'ensemble de notre ensemble de typographies pour assurer la cohérence dans l'ensemble de l'application, pour toutes les tailles et résolutions d'écran.

Taille de la police

Il existe deux façons de définir la taille de la police de votre application :

  1. Déclarer manuellement chacune des variantes de taille de police, pour chacun de vos points d'arrêt souhaités dans votre fichier Typography. 😱

  2. Utilisation de l'astucieux responsiveFontSizes de MUI aide pour le faire pour nous! 🍾

Pour cet exemple, nous implémenterons l'option 2 car elle réduit la quantité de code personnalisé que nous devons maintenir et définit toutes les tailles de police pour nous pour chaque point d'arrêt. Une démo interactive sur le fonctionnement de cette fonctionnalité est disponible ici

Tout ce que nous avons à faire est d'envelopper notre thème avec leur fonction.

// theme/index.tsx

import { createMuiTheme, responsiveFontSizes } from '@material-ui/core';

import { typography } from './typography';

export default responsiveFontSizes(createMuiTheme({
  typography
}))

Nos tailles de police sont désormais responsives ! Les captures d'écran suivantes illustrent l'évolution de la taille de police du H1 du mobile au bureau, chacune configurée par rapport aux points d'arrêt petit (sm), moyen (md) et grand (lg).

point d'arrêt:sm

point d'arrêt :md

point d'arrêt :lg

Si vous souhaitez modifier la force de la quantité de redimensionnement de la taille de la police entre les points d'arrêt, vous pouvez ajouter un factor option au responsiveFontSizes fonction.

// theme/index.tsx

import { createMuiTheme, responsiveFontSizes } from '@material-ui/core';

import { typography } from './typography';

export default responsiveFontSizes(createMuiTheme({
  typography
}), {
  factor: 1 // [default is 2] The higher the value, the less difference there is between font sizes on small screens. The lower the value, the bigger font sizes for small screens. The value must be greater than 1.
})

 Points d'arrêt

Paramétrage

Le thème de MUI implémente les points d'arrêt par défaut suivants :

  • xs, très petit :0px
  • petit, petit :600 px
  • dm, moyen :960px
  • lg, grand :1 280 px
  • xl, très grand :1 920 px

Personnellement, je n'ai jamais eu à modifier les paramètres de point d'arrêt, même si vous pouvez les reconfigurer.

Des informations sur la personnalisation des points d'arrêt sont disponibles ici.

Accéder aux points d'arrêt

Lorsque vous arriverez à l'étape de développement des composants, vous devrez éventuellement résoudre des problèmes de mise en page réactive pour rendre votre application accessible et aussi fluide que possible.

MUI vous offre de nombreuses façons de vous connecter à l'état du point d'arrêt du thème, que vous souhaitiez styliser statiquement votre composant et ses changements de point d'arrêt, ou observer les changements de point d'arrêt dans votre composant pour faire quelque chose de logique. Passons en revue quelques exemples.

Requêtes média CSS

Pour cet exemple, imaginez que vous avez un Card composant qui a un titre, du texte, puis un appel à l'action Button au fond. Vous êtes ensuite chargé de styliser le bouton par rapport à différents points d'arrêt.

Pseudo train de pensée

  • [points d'arrêt égaux ou inférieurs à sm ] le bouton doit s'étendre sur toute la largeur de la carte,
  • [points d'arrêt égaux ou supérieurs à md ] le bouton doit s'ancrer à droite en utilisant sa largeur d'origine.
  • [points d'arrêt égaux ou supérieurs à lg ] le bouton doit s'ancrer à droite en utilisant sa largeur d'origine et son rembourrage doit être plus grand.

Implémentation finale

// Example: CSS Media Queries

const styles = theme => ({
  button: {
    [theme.breakpoints.down('sm')]: {
      width: '100%'
    },
    [theme.breakpoints.up('md')]: {
      width: 'auto'
    },
    [theme.breakpoints.up('lg')]: {
      paddingLeft: '4rem',
      paddingRight: '4rem'
    },
  },
});

Quelques points à noter :

  1. breakpoints est une propriété exposée à partir de notre theme injecté (via le ThemeProvider HoC)
  2. breakpoints ont 4 fonctions que vous pouvez utiliser pour sélectionner vos points d'arrêt cibles :
  3. theme.breakpoints.up(clé)
  4. theme.breakpoints.down(clé)
  5. theme.breakpoints.only(clé)
  6. theme.breakpoints.between(début, fin)
  7. Déclarez vos points d'arrêt du plus petit au plus grand afin de conserver le principe de conception Mobile-First de MUI. Si vous ne le faites pas, vous pourriez rencontrer un comportement inattendu.

Requêtes média JS

Pour cet exemple, imaginez que vous avez un Table qui comporte de nombreuses colonnes et se lit de gauche à droite. Ce tableau se lit très bien sur des écrans plus grands, mais le concepteur a réajusté le tableau pour les écrans mobiles, d'où une deuxième interprétation du Table doit être rendu dans ce cas.

Pseudo train de pensée

  • [points d'arrêt égaux ou inférieurs à sm ] devrait rendre le MobileTable , sinon le LargerTable doit être rendu.

Mise en œuvre finale

// Example: JS Media Queries

import { useTheme } from '@material-ui/core/styles';
import useMediaQuery from '@material-ui/core/useMediaQuery';

function TableWrapper() {
  const theme = useTheme();
  const mobileBreakpoint = useMediaQuery(theme.breakpoints.down('sm'));

  if (mobileBreakpoint) {
    return <MobileTable />
  }
  return <LargerTable />
}

Quelques points à noter :

  1. Le useTheme hook est défini de sorte que le TableWrapper le composant a accès au Theme de l'application .
  2. Le useMediaQuery hook est défini et paramétré avec mon point d'arrêt souhaité pour le crochet à observer. Sa valeur initiale est soit true ou false , en fonction des dimensions calculées par les clients.
  3. useMediaQuery observer l'événement Windows Resize et recalculer en interne la valeur des crochets si la valeur actuelle du point d'arrêt du thème change.
  4. Rappelez-vous breakpoints.down(key) , breakpoints.up(key) inclut le key dans le cadre de sa vérification booléenne.

En savoir plus sur useMediaQuery .

Palette de couleurs

La couleur existe et la plupart ont la chance d'être témoins de sa gamme et de ses utilisations dans le monde. S'il est bien utilisé, il peut promouvoir votre marque et rappeler cognitivement aux gens votre marque, il peut indiquer un niveau de gravité et attirer l'œil. En fin de compte, la couleur a un sens.

Le thème de MUI vous permet de configurer une palette, qui est une "intention de couleur" de maquillage. Voici les intentions de couleurs et leurs utilisations.

  • principal - utilisé pour représenter les principaux éléments d'interface pour un utilisateur. Il s'agit de la couleur qui s'affiche le plus souvent sur les écrans et les composants de votre application.
  • secondaire - utilisé pour représenter des éléments d'interface secondaires pour un utilisateur. Il offre plus de façons d'accentuer et de distinguer votre produit. L'avoir est facultatif.
  • erreur - utilisé pour représenter des éléments d'interface dont l'utilisateur doit être informé.
  • avertissement - utilisé pour représenter des actions potentiellement dangereuses ou des messages importants.
  • informations - utilisé pour présenter à l'utilisateur des informations neutres et pas nécessairement importantes.
  • succès - utilisé pour indiquer la réussite d'une action déclenchée par un utilisateur. Si vous souhaitez en savoir plus sur la couleur, vous pouvez consulter la section couleur.

La capture d'écran suivante montre chaque intention de couleur et leurs valeurs par défaut :

Choisir vos couleurs

MUI est le cadeau qui ne cesse de donner ! L'équipe Material Design a créé un "outil de couleur" que vous pouvez utiliser pour brancher vos couleurs spécifiques et les voir visuellement par rapport aux composants de base de MUI. L'outil dispose également d'une fonctionnalité d'accessibilité que je vous encourage à utiliser car elle rendra compte de la lisibilité de vos couleurs.

Conception de matériaux :outil de couleur

Je continuerai à utiliser les couleurs de la marque Mechanical Rock :

  • Primaire :#40BFB4
  • Secondaire #E15554

L'outil calculera automatiquement les valeurs claires et foncées à partir de la couleur principale que vous avez fournie.

Appliquer la Palette

Une fois que vous avez finalisé vos couleurs primaires et secondaires, vous pouvez ensuite les configurer dans votre thème. Nous allons créer un nouveau fichier Palette pour gérer ce changement (comme nous l'avons fait pour Typographie).

// theme/palette.tsx

import { PaletteOptions } from '@material-ui/core/styles/createPalette';

export const palette: PaletteOptions = {
  primary: {
    // light: will be calculated from palette.primary.main,
    main: '#40bfb4',
    // dark: will be calculated from palette.primary.main,
    // contrastText: will be calculated to contrast with palette.primary.main
  },
  secondary: {
    // light: will be calculated from palette.primary.main,
    main: '#e05450',
    // dark: will be calculated from palette.secondary.main,
  },
  // Used by `getContrastText()` to maximize the contrast between
  // the background and the text.
  contrastThreshold: 3,
  // Used by the functions below to shift a color's luminance by approximately
  // two indexes within its tonal palette.
  // E.g., shift from Red 500 to Red 300 or Red 700.
  tonalOffset: 0.2,
}

Comme le suggèrent les commentaires dans l'extrait de code ci-dessus, vous pouvez laisser MUI calculer gratuitement les valeurs claires/foncées pour vous, sinon ajoutez-les manuellement pour chaque objet primaire et secondaire.

Même si les couleurs que vous avez choisies ont été déclarées éligibles dans "l'outil de couleur", il est toujours possible que votre texte de premier plan ne contraste pas bien avec les nuances d'arrière-plan de vos surfaces. Le contrastThreshold La propriété vous permet d'amplifier ou d'adoucir le contraste de votre texte par rapport à la couleur d'arrière-plan.

Si vous souhaitez baisser les lumières ou rendre une couleur plus vive lors d'événements tels que le survol d'un bouton, vous pouvez ajuster la quantité par rapport au tonalOffset propriété.

Ajoutons une section de couleur à notre application en procédant comme suit :

// src/ui/ColourPalette/index.tsx

import React from 'react';

import { Box, Grid, Typography } from '@material-ui/core';

function ColourBox({ intention, variant }: { intention: string; variant: string; }) {
  const bgColor = `${intention}.${variant}`;
  const color = intention === 'text' ? 'background.paper' : `${intention}.contrastText`;
  return (
    <Grid item xs={12} sm={4}>
      <Box bgcolor={bgColor} color={color} p={4}>
        <strong>{bgColor}</strong>
      </Box>
    </Grid>
  )
}

const palette = [
  { intention: 'primary', variant: 'main' },
  { intention: 'secondary', variant: 'main' },
  { intention: 'error', variant: 'main' },
  { intention: 'warning', variant: 'main' },
  { intention: 'info', variant: 'main' },
  { intention: 'success', variant: 'main' },
  { intention: 'text', variant: 'primary' },
  { intention: 'text', variant: 'secondary' },
  { intention: 'text', variant: 'disabled' }
]
export default function ColourPalette() {
  return (
    <>
      <Typography variant="h2">Colour Palette</Typography>
      <br />
      <Grid container spacing={1}>
        {palette.map((p, i) => <ColourBox key={i} {...p} />)}
      </Grid>
    </>
  )
}

Ajoutez ensuite la nouvelle section à notre application :

// src/app.tsx

import { CssBaseline, Divider, ThemeProvider } from '@material-ui/core';

import Theme from './theme';
import ColourPalette from './ui/ColourPalette';
import Typography from './ui/Typographies';

export default function App() {
  return (
    <ThemeProvider theme={Theme}>
      <CssBaseline />
      <Typography />
      <Divider />
      <ColourPalette />
    </ThemeProvider>
  );
}

Vous devriez finir par voir ceci :

Boutons

MUI propose 3 variantes de boutons, Contenu, Texte, Contour.

Bouton contenu

Les boutons Contenir doivent être utilisés pour les actions de l'utilisateur principal. Ils sont prononcés et surélevés en surface.

Bouton Texte

Les boutons de texte sont généralement utilisés pour des actions moins prononcées, y compris celles situées en Dialogs et Cards . Dans les cartes, les boutons de texte aident à maintenir l'accent sur le contenu de la carte.

Bouton avec contour

Les boutons soulignés sont des boutons moyennement accentués. Ils contiennent des actions qui sont importantes, mais qui ne sont pas l'action principale dans une application. Les boutons soulignés sont également une alternative moins accentuée aux boutons contenus, ou une alternative plus accentuée aux boutons de texte.

Ajoutons une section de boutons à notre application en procédant comme suit :

// ui/Buttons/index.tsx

import React from 'react';

import { Button, Container, Typography } from '@material-ui/core';

export default function Buttons() {
  return (
    <>
      <Typography variant="h2">Buttons</Typography>
      <br />

      <Container maxWidth="xs">
        <Typography variant="subtitle1" align="center">Contained</Typography>
        <Button variant="contained" color="default">Default</Button>
        <Button variant="contained" color="primary">Primary</Button>
        <Button variant="contained" color="secondary">Secondary</Button>
        <Button variant="contained" color="primary" disabled>Disabled</Button>
      </Container>
      <br />

      <Container maxWidth="xs">
        <Typography variant="subtitle1" align="center">Text</Typography>
        <Button variant="text" color="default">Default</Button>
        <Button variant="text" color="primary">Primary</Button>
        <Button variant="text" color="secondary">Secondary</Button>
        <Button variant="text" color="primary" disabled>Disabled</Button>
      </Container>
      <br />

      <Container maxWidth="xs">
        <Typography variant="subtitle1" align="center">Outlined</Typography>
        <Button variant="outlined" color="default">Default</Button>
        <Button variant="outlined" color="primary">Primary</Button>
        <Button variant="outlined" color="secondary">Secondary</Button>
        <Button variant="outlined" color="primary" disabled>Disabled</Button>
      </Container>
    </>
  )
}

N'oubliez pas de l'ajouter à votre App.tsx fichier pour voir le nouveau contenu !

Nous devrions voir quelque chose comme ceci :

Échafaudez votre application

Définir la mise en page initiale de votre application peut être intimidant. Même si la plupart des mises en page de sites Web sont assez cohérentes de nos jours, il existe plus d'une façon d'écorcher un chat ! Trop d'implémentations de sites Web manquent de HTML bien schématique, ce qui me fait penser qu'il y a un manque de connaissances sur ce sujet. Par exemple, les sites Web qui ont plusieurs balises H1, une hiérarchie d'en-tête brisée, un div inutile utilisation qui devrait être remplacée par des balises mieux ciblées.

Avant de pouvoir commencer à construire notre mise en page, nous devons savoir où se trouvent les principaux points de repère. La navigation du menu principal sera-t-elle en haut de la page (sera-t-elle corrigée ?) ou sera-t-elle ancrée à gauche de la page ?
Quel type de contenu devez-vous afficher ? Contenu de type blog où le contenu est mieux présenté dans le canal central ou multimédia, où le contenu peut être en mosaïque.

Dans notre cas, l'échafaudage ressemblera à ceci pour mobile :

Et pour le bureau :

Barre d'applications

Créez un nouveau fichier pour gérer votre App Bar :

// src/components/AppBar/index.tsx

import React from 'react';

import { AppBar as MuiAppBar, IconButton, Toolbar, Typography } from '@material-ui/core';
import { MenuRounded } from '@material-ui/icons';

export default function AppBar() {
  return (
    <MuiAppBar color="primary" position="sticky">
      <Toolbar>
        <IconButton edge="start" aria-label="menu">
          <MenuRounded />
        </IconButton>
        <Typography variant="h6">
          Component Library
        </Typography>
      </Toolbar>
    </MuiAppBar>
  )
}

Quelques points à noter :

  1. Nous devons caster le AppBar importé module à un nouveau nom MuiAppBar afin que nous puissions exporter notre propre version du AppBar aller de l'avant.
  2. Nous implémentons le [position="sticky"] prop contre le MuiAppBar . C'est ainsi que l'AppBar restera en haut de la fenêtre d'affichage, même lorsque vous faites défiler au-delà de sa position initiale.
  3. Nous implémentons le [edge="start"] prop contre le IconButton . Cela appliquera du CSS pour ancrer l'icône à gauche, moins son décalage de marge d'origine.

Nous nous retrouvons avec ceci :

Contenu du corps

C'est là que la plupart de votre public passera son temps à découvrir, interagir ou rechercher des informations dans votre application. Le contenu du corps lui-même peut obtenir de nombreuses mises en page en interne, mais ce qui est important, sa couche abstraite doit être cohérente.

Créez un nouveau fichier pour gérer votre contenu corporel :

// src/components/BodyContent/index.tsx

import React from 'react';

import { Divider, makeStyles } from '@material-ui/core';

import ColourPalette from '../../ui/ColourPalette';
import Typographies from '../../ui/Typographies';

const useStyles = makeStyles(() => ({
  root: {
    margin: '0 auto',
    maxWidth: '57rem',
    padding: '2rem 0'
  }
}))

export default function BodyContent() {
  const classes = useStyles();

  return (
    <main className={classes.root}>
      <Typographies />
      <Divider />
      <ColourPalette />
    </main>
  )
}

Quelques points à noter :

  1. Nous avons créé notre premier exemple CSS-in-JSS. Nous avons dû le faire pour définir certains styles par rapport à l'élément racine de ce composant, <main> . makeStyles exporter les styles calculés en tant que crochet, lorsque nous avons attribué à une variable étendue nommée useStyles . useStyles est alors déclaré dans le corps de notre BodyContent composant afin que nous y ayons accès.
  2. margin: '0 auto' s'assurera que le <main> le bloc est centré dans la page
  3. maxWidth: '57rem' définira la largeur maximale du <main> bloc, je me sentais représenté une bonne largeur de colonne lisible pour les écrans plus grands.
  4. padding: '2rem 0' appliquera une gouttière cohérente de 2rem en haut et en bas du <main> bloquer.
  5. Nous avons depuis migré les composants Typographies et ColourPalette du app.tsx fichier dans ce fichier.
  6. Notez l'utilisation du HTML main Étiquette. Il s'agit d'une balise plus précise à utiliser dans ce cas, car elle encapsule l'intention pour le reste du contenu.

Voici une capture d'écran de bureau montrant le modèle de boîte de notre <main> élément:

Navigation dans le menu principal

Le menu principal est le principal moyen pour les utilisateurs de naviguer dans votre application. Il doit contenir toutes les zones principales de l'application et indiquer où l'utilisateur se situe actuellement dans la hiérarchie.

Créez un nouveau fichier pour gérer votre navigation dans le menu principal :

// src/components/MainMenu/index.tsx

import React from 'react';

import { Drawer, List, ListItem, ListItemText } from '@material-ui/core';

function MenuItems() {
  return (
    <List>
      {['1', '2', '3'].map(item => (
        <ListItem button key={item}>
          <ListItemText primary={`Menu Item #${item}`} />
        </ListItem>
      ))}
    </List>
  )
}

type Props = {
  openMenu: boolean;
  setOpenMenu: React.Dispatch<React.SetStateAction<boolean>>;
}

export default function MainMenu({ openMenu, setOpenMenu }: Props) {
  return (
    <nav aria-label="main menu navigation">
      <Drawer
        anchor="left"
        disablePortal
        onClose={() => setOpenMenu(false)}
        open={openMenu}
        variant="temporary"
      >
        <MenuItems />
      </Drawer>
    </nav>
  );
}

Quelques points à noter :

  1. Nous utilisons le Drawer de MUI composant pour contenir le contenu de nos éléments de menu.
  2. [anchor="left"] prop est utilisé pour déclarer d'où nous voudrions que la transition Menu it s'effectue.
  3. J'ai personnellement déclaré [disablePortal=true] ici pour que le HTML vive à l'intérieur du <nav> élément, le rendant ainsi plus accessible et schématiquement correct.
  4. Le onClose la fonction de rappel n'est invoquée que si l'écouteur de clic d'arrière-plan est présent ; fixé par le [variant="temporary"] propriété.
  5. [open=true] fera la transition vers l'intérieur du menu et l'inverse fera la transition vers la sortie du menu.

Nous devons ensuite colocaliser le MainMenu avec notre AppBar composant car il a le Menu bouton que nous devons câbler.

// src/components/AppBar/index.tsx

import React from 'react';

import { AppBar as MuiAppBar, IconButton, Toolbar, Typography } from '@material-ui/core';
import { MenuRounded } from '@material-ui/icons';

import MainMenu from '../MainMenu';

export default function AppBar() {
  const [openMenu, setOpenMenu] = React.useState(false);

  return (
    <>
      <MuiAppBar color="primary" position="sticky">
        <Toolbar>
          <IconButton
            edge="start"
            aria-label="menu"
            onClick={() => setOpenMenu(state => !state)}
          >
            <MenuRounded />
          </IconButton>
          <Typography variant="h6">
            Component Library
          </Typography>
        </Toolbar>
      </MuiAppBar>
      <MainMenu openMenu={openMenu} setOpenMenu={setOpenMenu} />
    </>
  )
}

On finit par ça :

🙏 Clôture

À ce stade, votre application doit être enveloppée avec un fournisseur de thèmes.
Vous devez avoir suffisamment de connaissances sur la façon de remplacer les styles des composants MUI ainsi que sur la façon de créer vos propres styles à côté de vos propres composants.

Vous êtes maintenant prêt à passer au prochain épisode dans lequel je vous expliquerai comment implémenter le routage dans votre application, en abordant les sujets suivants :

  • Comment configurer le routage dans votre application,
  • Routes avec paramètres,
  • Acheminer les crochets,
  • Transitions de routage

Ne soyez pas timide, contactez-nous !