Realizzare applicazioni React utilizzando la libreria Material-UI
Lavorare con React (1) per realizzare funzionalità lato frontend è un’operazione resa più semplice dall’uso di librerie di componenti. Una delle più usate è Material-UI (2).
Questa libreria offre i componenti base tipici di una libreria adottando come linea guida il linguaggio di design Material Design (3) di Google. Un’altra sua caratteristica è il mobile first, ovvero risulta facile produrre una UI che si adatta molto facilmente a schermi di grandi dimensioni, smartphone e tablet.
Nei prossimi paragrafi Manuel Togni vi spiegherà quanto appreso sull’implementazione di classi React con l’uso di Material-UI.
React e Material-UI – premesse
Vale la pena fare una premessa. Per utilizzare efficacemente la libreria è molto utile fare riferimento alla documentazione piuttosto completa che si può trovare sul sito ufficiale. Tale documentazione va di pari passo agli aggiornamenti della libreria quindi prestare attenzione quando si cercano informazioni per una certa versione.
Un’altra nota importante è che la maggior parte della documentazione fa esempi di componenti con stili definiti direttamente al loro interno, dove vengono applicati. In generale sembra essere un buon modo di gestire lo stile con questa libreria. Se si adotta questo approccio sarà necessario abituarsi alla sintassi delle proprietà CSS scritte in camel case. Ad esempio font-size diventa fontSize, mentre background-color backgroundColor. Ciò avviene perché le proprietà vengono scritte in un oggetto Javascript.
Material-UI
La libreria si basa su un tema predefinito che può essere personalizzato in base alle esigenze.
Una volta creato il proprio tema bisogna avere cura di avere il componente ThemeProvider come wrapper alla root dei componenti dell’applicazione. Cosi facendo si può accedere alle proprietà definite all’interno del tema in tutti i componenti.
Alcune delle principali proprietà che possono essere definite sono palette colori, typography e spacing unit (utile per definire in modo consistente padding e margin in tutti i componenti che si andranno a creare).
React e Material-UI: personalizzare i componenti
Per poter utilizzare efficacemente la libreria sarà necessario sfruttare sia le proprietà che i componenti base mettono a disposizione sia fare l’override degli stili applicati di default. Per fare ciò esistono tre possibilità di ovverride:
- con className: ogni componente supporta la proprietà className che si aspetta uno stile che poi verrà applicato alla root dell’elemento, ovvero la classe principale del componente.
<IconButton aria-label="Open drawer" onClick={props.onClick} className={classes.menuIcon} > {props.icon} </IconButton>
- attraverso classes: nel caso in cui className non sia sufficiente perché ad esempio vengono applicate delle classi più specifiche al componente. In questo caso è necessario passare dalla proprietà classes per personalizzare il CSS di default. La lista di proprietà di classes per ogni componente è documentata nella pagina relativa alle sue API. In particolare bisogna far riferimento alla sezione CSS e verificare quali sono le rule name disponibili. Questo funziona bene nel caso in cui si ha già un’idea di quale di queste classi viene applicata da Material-UI per il componente che stiamo usando. Diversamente può essere utile passare dai Chrome DevTools (4) andando a ispezionare l’elemento in pagina e facilmente vedere le rule name che vengono applicate. Il formato adottato per i nomi delle classi è il seguente:
Mui[component name]-[style rule name]-[UUID]
<ExpansionPanelSummary classes={{ root: classes.accordionRoot, content: classes.accordionSummary, expanded: classes.accordionSummaryExpanded }} >
- con il tema: è possibile usare il tema per modificare gli stili alla base dei componenti che andremo ad usare. Un motivo per cui ha senso fare questa scelta è quando si è sicuri che in tutti i punti in cui si userà un certo componente si ha bisogno che venga applicato uno stile specifico. In questo caso non avrebbe senso dover duplicare la modifica allo stile in ogni punto in cui sarà utilizzato. Qui un esempio:
const theme = createMuiTheme({ overrides: { MuiButton: { root: { fontSize: '1rem', }, }, }, });
Notare come in questo caso il componente Button viene indicato attraverso il nome MuiButton. Questo vale per tutti i componenti per i quali si vuole fare l’override nel tema. Precedere sempre il nome con Mui.
React e Material-UI: pseudo classi
Gli stati particolari del componente come hover, focus, disabled e selected possono essere stilizzati con una specificità CSS (CSS specificity) maggiore.
Un modo possibile è usare la $ruleName nella dichiarazione dello stile come nel seguente esempio.
const styles = { root: { '&$disabled': { color: 'white', }, }, disabled: {}, };
In questo caso per poter effettivamente ottenere il risultato che ci si aspetta è necessario applicare entrambe le classi create:
<Button disabled classes={{ root: classes.root, disabled: classes.disabled, }} > classes state </Button>
Un altro esempio può essere con il classico hover:
menuLayer: { display: "flex", "&:hover": { backgroundColor: "rgba(237, 232, 228, 0.7)" }, "&:hover $iconOnHover": { display: "initial" }, "&:hover $icon": { display: "none" } }, icon: {}, iconOnHover: { display: "none" } }
In questo caso si sta andando a fare un’operazione un po’ più complicata. In particolare nel caso di hover sull’elemento che avrà la classe menuLayer si va a settare uno stile per altre due classi (icon e iconOnHover) che verranno utilizzate da altri elementi nel DOM.
React e Material-UI: classi multiple e opzionali
Quando serve applicare più classi diverse oppure alternativamente una classe oppure un’altra (tipicamente si valuta una proprietà che ci da informazioni su un certo comportamento assunto dal componente) è necessario sfruttare le template string, come mostrato nell’esempio seguente:
<IconButton onClick={props.onSearch} disabled={!props.searchText} className={`${classes.iconWrapper} ${classes.searchIconWrapper}`} > <DynamicIcon imageRef={"search"} /> </IconButton>
Il prossimo esempio invece è con la classe opzionale:
<IconButton onClick={() => props.deletePostPart()} className={`${classes.deleteIcon} ${ props.currentlyEditingPart ? classes.iconOnEdit : "" }`} > <Icon>delete</Icon> </IconButton>
In quest’ultimo caso o viene applicata la classe aggiuntiva iconOnEdit oppure viene applicata solo deleteIcon.
Prima di salutarvi, vi lascio con un consiglio: per scrivere il carattere ` (accento grave) su Windows basta installare la tastiera inglese (US) dopodiché con la combinazione di tasti Windows + barra spaziatrice
effettuate il cambio della lingua. Per ottenere l’accento grave, basterà premere il tasto \.