Implementarea modului întunecat în aplicațiile React folosind componente cu stil
Publicat: 2022-03-10Una dintre caracteristicile software cel mai frecvent solicitate este modul întunecat (sau modul noapte, așa cum îl numesc alții). Vedem modul întunecat în aplicațiile pe care le folosim în fiecare zi. De la aplicații mobile la aplicații web, modul întunecat a devenit vital pentru companiile care doresc să aibă grijă de ochii utilizatorilor lor.
Modul întunecat este o caracteristică suplimentară care afișează în mare parte suprafețe întunecate în interfața de utilizare. Majoritatea companiilor importante (cum ar fi YouTube, Twitter și Netflix) au adoptat modul întunecat în aplicațiile lor mobile și web.
Deși nu vom aprofunda în React și componentele stilate, ar fi utilă cunoștințe de bază despre React, CSS și componentele stilate. Acest tutorial va aduce beneficii celor care doresc să-și îmbunătățească aplicațiile web, oferindu-le celor care iubesc modul întunecat.
Cu câteva zile înainte de scrierea acestui articol, StackOverflow a anunțat lansarea modului întunecat, oferind utilizatorilor șansa de a comuta între cele două moduri.
Modul întunecat reduce oboseala ochilor și vă ajută atunci când lucrați o perioadă lungă de timp la un computer sau un telefon mobil.
Ce este modul întunecat?
Modul întunecat este schema de culori a oricărei interfețe care afișează text deschis și elemente de interfață pe un fundal întunecat, ceea ce face ca ecranul să fie puțin mai ușor de privit la telefoane mobile, tablete și computere. Modul întunecat reduce lumina emisă de ecran, menținând în același timp raporturile minime de contrast de culoare necesare pentru lizibilitate.
De ce ar trebui să îți pese de modul întunecat?
Modul întunecat îmbunătățește ergonomia vizuală prin reducerea oboselii ochilor, ajustând ecranul la condițiile actuale de lumină și oferind ușurință în utilizare pe timp de noapte sau în medii întunecate.
Înainte de a implementa modul întunecat în aplicația noastră, să ne uităm la beneficiile acestuia.
Economie de baterie
Modul întunecat în aplicațiile web și mobile poate prelungi durata de viață a bateriei unui dispozitiv. Google a confirmat că modul întunecat pe ecranele OLED a fost de mare ajutor pentru durata de viață a bateriei.
De exemplu, la 50% luminozitate, modul întunecat din aplicația YouTube economisește cu aproximativ 15% mai multă energie pe ecran decât un fundal alb plat. La 100% luminozitatea ecranului, interfața întunecată economisește 60% din energia ecranului.
Modul întunecat este frumos
Modul întunecat este frumos și poate spori în mod semnificativ atractivitatea ecranului.
În timp ce majoritatea produselor au acel aspect alb și blând, modul întunecat oferă ceva diferit, care se simte misterios și nou.
De asemenea, oferă oportunități excelente de a prezenta conținut grafic, cum ar fi tablouri de bord, imagini și fotografii într-un mod nou.
Acum că știți de ce ar trebui să implementați modul întunecat în următoarea aplicație web, haideți să ne aprofundăm în componentele stilate, care este resursa definitorie a acestui tutorial.
Modul întunecat este schema de culori a oricărei interfețe care afișează text deschis și elemente de interfață pe un fundal întunecat, ceea ce îl face puțin mai ușor de văzut pe telefoanele mobile, tablete și computere.
„
Ce sunt componentele stilate?
Pe parcursul acestui articol, vom folosi foarte des biblioteca de componente cu stil. Au existat întotdeauna multe moduri de a stila o aplicație web modernă. Există metoda tradițională de stilare la nivel de document, care include crearea unui fișier index.css
și legarea acestuia la HTML sau stilarea în interiorul fișierului HTML.
S-au schimbat multe în modul în care aplicațiile web sunt stilate recent, de la introducerea CSS-in-JS.
CSS-in-JS se referă la un model în care CSS este compus folosind JavaScript. Utilizează literale șablon etichetate pentru a stila componentele într-un fișier JavaScript.
Pentru a afla mai multe despre CSS-in-JS, consultați articolul Anna Monus pe acest subiect.
styled-components este o bibliotecă CSS-in-JS care vă permite să utilizați toate caracteristicile CSS pe care le iubiți, inclusiv interogări media, pseudo-selectori și imbricare.
De ce componente stilate?
styled-components a fost creat din următoarele motive:
- Fără nume de clasă iad
În loc să vă zgâriați din cap pentru a găsi un nume de clasă pentru un element, styled-components generează nume de clasă unice pentru stilurile dvs. Nu va trebui niciodată să vă faceți griji cu privire la greșeli de ortografie sau la utilizarea numelor de clasă care nu au sens. - Folosind recuzită
componentele cu stil ne permit să extindem proprietățile de stil folosind parametrulprops
, folosit în mod obișnuit în React - astfel, afectând dinamic senzația unei componente prin starea aplicației. - Suporta sintaxa Sass
Scrierea din cutie a sintaxei Sass fără a fi nevoie să configurați preprocesoare sau instrumente de construcție suplimentare este posibilă cu componentele stilate. În definițiile stilului dvs., puteți utiliza caracterul&
pentru a viza componenta curentă, utilizați pseudo-selectori și experimentați imbricarea. - Tematică
Componentele cu stil au suport complet pentru tematică prin exportul unei componenteThemeProvider
. Această componentă oferă o temă tuturor componentelor React din interiorul său prin intermediul API-ului Context. În arborele de randare, toate componentele stilizate vor avea acces la tema furnizată, chiar și atunci când au mai multe niveluri adânci. Pe măsură ce continuăm în acest tutorial, ne vom aprofunda caracteristicile tematice ale componentelor stilizate.
Pentru a afla mai multe avantaje ale componentelor stilizate, consultați articolul lui Kris Guzman.
Implementarea modului întunecat
În acest articol, vom implementa modul întunecat pe o pagină web simplă asemănătoare YouTube.
Pentru a continua, asigurați-vă că ați clonat depozitul original din ramura de starter
.
Configurare
Să instalăm toate dependențele din fișierul nostru package.json
. Din terminal, rulați următoarea comandă:
npm install
După instalarea cu succes, rulați npm start
. Iată cum arată pagina web fără modul întunecat implementat pe ea.
Pentru a instala styled-components
, în terminalul dvs. rulați npm install styled-components
.
Implementarea
Pentru a implementa modul întunecat, trebuie să creăm patru componente diferite.
-
Theme
Acesta conține proprietățile de culoare ale temelor noastre luminoase și întunecate. -
GlobalStyles
Acesta conține stilurile globale pentru întregul document. -
Toggler
Acesta deține elementul buton care comută funcționalitatea. -
useDarkMode
Acest cârlig personalizat gestionează logica din spatele schimbării temei și persistența temei noastre în localStorage.
Componenta Temă
În folderul src
, veți vedea componente în folderul components
. Creați un fișier Themes.js
și adăugați următorul cod la acesta.
export const lightTheme = { body: '#FFF', text: '#363537', toggleBorder: '#FFF', background: '#363537', } export const darkTheme = { body: '#363537', text: '#FAFAFA', toggleBorder: '#6B8096', background: '#999', }
Aici, am definit și exportat obiecte lightTheme
și darkTheme
cu variabile de culoare distincte. Simțiți-vă liber să experimentați și să personalizați variabilele potrivite dvs.
Componenta globalStyles
Rămânând în folderul de components
, creați un fișier globalStyles.js
și adăugați următorul cod:
import { createGlobalStyle} from "styled-components" export const GlobalStyles = createGlobalStyle` body { background: ${({ theme }) => theme.body}; color: ${({ theme }) => theme.text}; font-family: Tahoma, Helvetica, Arial, Roboto, sans-serif; transition: all 0.50s linear; } `
Am importat createGlobalStyle
din componentele cu stil. Metoda createGlobalStyle
înlocuiește metoda injectGlobal, acum depreciată, din versiunea 3 a componentelor stilate. Această metodă generează o componentă React, care, atunci când este adăugată în arborele de componente, va injecta stiluri globale în document, în cazul nostru, App.js
.
Am definit o componentă GlobalStyle
și am atribuit proprietăți de background
și color
valorilor din obiectul temă. Astfel, de fiecare dată când comutăm comutatorul, valorile se vor schimba în funcție de tema întunecată sau obiectele cu temă luminoasă pe care le transmitem la ThemeProvider
(care vor fi create ulterior, pe măsură ce procedăm).
Proprietatea de tranziție de 0.50s
permite ca această modificare să aibă loc puțin mai ușor, astfel încât, pe măsură ce comutăm înainte și înapoi, putem vedea schimbările care se întâmplă.
Crearea unei funcționalități de comutare a temei
Pentru a implementa funcționalitatea de comutare a temei, trebuie să adăugăm doar câteva linii de cod. În fișierul App.js
, adăugați următorul cod (rețineți că codul evidențiat este ceea ce ar trebui să adăugați):
import React, { useState, useEffect } from "react";
import {ThemeProvider} from "styled-components"; import { GlobalStyles } from "./components/Globalstyle"; import { lightTheme, darkTheme } from "./components/Themes"
import "./App.css"; import dummyData from "./data"; import CardList from "./components/CardList"; const App = () => { const [videos, setVideos] = useState([]);
const [theme, setTheme] = useState('light'); const themeToggler = () => { theme === 'light' ? setTheme('dark') : setTheme('light') }
useEffect(() => { const timer = setTimeout(() => { setVideos(dummyData); }, 1000); return () => clearTimeout(timer); }, []); return (
<ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}> <> <GlobalStyles/>
<div className="App">
<button onClick={themeToggler}>Switch Theme</button>
{ videos.map((list, index) => { return ( <section key={index}> <h2 className="section-title">{list.section}</h2> <CardList list={list} /> <hr /> </section> ); })} </div>
</> </ThemeProvider>
); }; export default App;
Codul evidențiat este cel nou adăugat la App.js
Am importat ThemeProvider
din styled-components
. ThemeProvider
este o componentă de ajutor din biblioteca de componente cu stil care oferă suport pentru tematică. Această componentă de ajutor injectează o temă în toate componentele React de sub ea însăși prin API-ul Context.
În arborele de randare, toate componentele stilizate vor avea acces la tema furnizată, chiar și atunci când au mai multe niveluri adânci. Consultați secțiunea „Teming”.
Apoi, importăm pachetul ./components/Globalstyle
GlobalStyle
În cele din urmă, de sus, importăm atât obiectele lightTheme
, cât și darkTheme
din ./components/Themes
.
Pentru a crea o metodă de comutare, avem nevoie de o stare care să mențină valoarea inițială a culorii temei noastre. Deci, creăm o stare de theme
și setăm starea inițială la light
, folosind cârligul useState
.
Acum, pentru funcționalitatea de comutare.
Metoda themeToggler
folosește un operator ternar pentru a verifica starea theme
și comută între întuneric sau lumină în funcție de valoarea condiției.
ThemeProvider
, o componentă de ajutor pentru componente cu stil, include totul în instrucțiunea return
și injectează orice componente de sub ea. Amintiți-vă că GlobalStyles
injectează stiluri globale în componentele noastre; prin urmare, este numit în interiorul componentei ThemeProvider
.
În cele din urmă, am creat un buton cu un eveniment onClick
care îi atribuie metoda themeToggler
.
Să vedem rezultatul până acum.
Fișierul nostru App.js
trebuie refactorizat; o mare parte din codul său nu este USCAT. (DRY înseamnă „nu te repeta”, un principiu de bază al dezvoltării de software menit să reducă repetarea.) Toată logica pare să fie în App.js
; este o bună practică să ne separăm logica de dragul clarității. Deci, vom crea o componentă care se ocupă de funcționalitatea de comutare.
Comutați componentă
Încă în folderul components
, creați un fișier Toggler.js
și adăugați următorul cod la acesta:
import React from 'react' import { func, string } from 'prop-types'; import styled from "styled-components" const Button = styled.button` background: ${({ theme }) => theme.background}; border: 2px solid ${({ theme }) => theme.toggleBorder}; color: ${({ theme }) => theme.text}; border-radius: 30px; cursor: pointer; font-size:0.8rem; padding: 0.6rem; } \`; const Toggle = ({theme, toggleTheme }) => { return ( <Button onClick={toggleTheme} > Switch Theme </Button> ); }; Toggle.propTypes = { theme: string.isRequired, toggleTheme: func.isRequired, } export default Toggle;
Pentru a menține lucrurile în ordine, ne-am stilat butonul de comutare în componenta Toggle
, folosind funcția de styled
din componentele stilate.
Acesta este doar pentru prezentare; puteți modela butonul după cum credeți de cuviință.
În interiorul componentei Toggle
, trecem două elemente de recuzită:
-
theme
furnizează tema curentă (luminoasă sau întunecată); - funcția
toggleTheme
va fi folosită pentru a comuta între teme.
Apoi, returnăm componenta Button
și atribuim o funcție toggleTheme
evenimentului onClick
.
În cele din urmă, folosim propTypes
pentru a ne defini tipurile, asigurându-ne că theme
noastră este un string
și isRequired
, în timp ce toggleTheme
este func
și isRequired
.
Utilizarea cârligelor personalizate ( useDarkMode
)
La construirea unei aplicații, scalabilitatea este primordială, ceea ce înseamnă că logica noastră de business trebuie să fie reutilizabilă, astfel încât să o putem folosi în multe locuri și chiar în diferite proiecte.
De aceea, ar fi grozav să mutăm funcționalitatea noastră de comutare într-o componentă separată. Pentru asta, ne-am crea propriul cârlig personalizat.
Să creăm un fișier nou numit useDarkMode.js
în folderul components
și să ne mutăm logica în acest fișier, cu câteva modificări. Adăugați următorul cod la fișier:
import { useEffect, useState } from 'react'; export const useDarkMode = () => { const [theme, setTheme] = useState('light'); const setMode = mode => { window.localStorage.setItem('theme', mode) setTheme(mode) }; const themeToggler = () => { theme === 'light' ? setMode('dark') : setMode('light') }; useEffect(() => { const localTheme = window.localStorage.getItem('theme'); localTheme && setTheme(localTheme) }, []); return [theme, themeToggler] };
Am adăugat câteva lucruri aici.
-
setMode
FolosimlocalStorage
pentru a persista între sesiuni în browser. Deci, dacă un utilizator a ales tema întunecată sau deschisă, asta va primi la următoarea vizită la aplicație sau dacă reîncarcă pagina. Prin urmare, această funcție stabilește starea noastră și transmitetheme
cătrelocalStorage
. -
themeToggler
Această funcție folosește un operator ternar pentru a verifica starea temei și comută între întuneric sau lumină în funcție de adevărul condiției. -
useEffect
Am implementat cârliguluseEffect
pentru a verifica montarea componentelor. Dacă utilizatorul a selectat anterior o temă, o vom trece la funcția noastrăsetTheme
. La final, vom returnatheme
noastră, care conținetheme
aleasă și funcțiathemeToggler
pentru a comuta între moduri.
Cred că veți fi de acord că componenta noastră în modul întunecat arată elegant.
Să mergem la App.js
pentru ultimele retușuri.
import React, { useState, useEffect } from "react"; import {ThemeProvider} from "styled-components";
import {useDarkMode} from "./components/useDarkMode"
import { GlobalStyles } from "./components/Globalstyle"; import { lightTheme, darkTheme } from "./components/Themes" import Toggle from "./components/Toggler" import "./App.css"; import dummyData from "./data"; import CardList from "./components/CardList"; const App = () => { const [videos, setVideos] = useState([]);
const [theme, themeToggler] = useDarkMode(); const themeMode = theme === 'light' ? lightTheme : darkTheme;
useEffect(() => { const timer = setTimeout(() => { setVideos(dummyData); }, 1000); return () => clearTimeout(timer); }, []); return (
<ThemeProvider theme={themeMode}>
<> <GlobalStyles/> <div className="App">
<Toggle theme={theme} toggleTheme={themeToggler} />
{ videos.map((list, index) => { return ( <section key={index}> <h2 className="section-title">{list.section}</h2> <CardList list={list} /> <hr /> </section> ); })} </div> </> </ThemeProvider> ); }; export default App;
Codul evidențiat este nou adăugat în App.js
.
În primul rând, importăm cârligul nostru personalizat, destructuram theme
și elementele de recuzită themeToggler
și le setăm cu funcția useDarkMode
.
Rețineți că metoda useDarkMode
înlocuiește starea theme
noastre, care era inițial în App.js
.
Declarăm o variabilă themeMode
, care redă fie o temă deschisă, fie o temă întunecată, în funcție de starea modului theme
la momentul respectiv.
Acum, componenta noastră de înfășurare ThemeProvider
este atribuită variabilei themeMode recent creată themeMode
theme
.
Și, în sfârșit, în locul butonului obișnuit, trecem componenta Toggle
.
Amintiți-vă că, în componenta noastră Toggle
, am definit și stilat un buton și le-am transmis atât theme
, cât și toggleTheme
ca elemente de recuzită. Deci, tot ce trebuie să facem este să transmitem aceste elemente de recuzită în mod corespunzător la componenta Toggle
, care va acționa ca butonul nostru în App.js
Da! Modul nostru întunecat este setat și persistă, fără a-și schimba culoarea atunci când pagina este reîmprospătată sau vizitată într-o filă nouă.
Să vedem rezultatul în acțiune:
Aproape totul funcționează bine, dar există un lucru mic pe care îl putem face pentru a ne face experiența splendidă. Comutați la tema întunecată și apoi reîncărcați pagina. Vedeți că culoarea albastră a butonului se încarcă înainte de gri pentru un scurt moment? Acest lucru se întâmplă deoarece cârligul nostru useState
inițiază inițial tema light
. După aceea, useEffect
rulează, verifică localStorage
și abia apoi setează theme
la dark
. Să trecem la cârligul nostru personalizat useDarkMode.js
și să adăugăm un mic cod:
import { useEffect, useState } from 'react'; export const useDarkMode = () => { const [theme, setTheme] = useState('light');
const [mountedComponent, setMountedComponent] = useState(false)
const setMode = mode => { window.localStorage.setItem('theme', mode) setTheme(mode) }; const themeToggler = () => { theme === 'light' ? setMode('dark') : setMode('light') }; useEffect(() => { const localTheme = window.localStorage.getItem('theme'); localTheme ? setTheme(localTheme) : setMode('light')
setMountedComponent(true)
}, []); return [theme, themeToggler,
}, []); return [theme, themeToggler,
mountedComponent
]
};
Codul evidențiat este singurul adăugat la useDarkMode.js
. Am creat o altă stare numită mountedComponent
și am setat valoarea implicită la false
folosind hook-ul useState
. Apoi, în interiorul cârligului useEffect
, setăm starea mountedComponent
la true
folosind setMountedComponent
. În cele din urmă, în matricea de return
, includem starea mountedComponent
.
În cele din urmă, să adăugăm un pic de cod în App.js
pentru ca totul să funcționeze.
import React, { useState, useEffect } from "react"; import {ThemeProvider} from "styled-components"; import {useDarkMode} from "./components/useDarkMode" import { GlobalStyles } from "./components/Globalstyle"; import { lightTheme, darkTheme } from "./components/Themes" import Toggle from "./components/Toggler" import "./App.css"; import dummyData from "./data"; import CardList from "./components/CardList"; const App = () => { const [videos, setVideos] = useState([]);
const [theme, themeToggler, mountedComponent] = useDarkMode();
const themeMode = theme === 'light' ? lightTheme : darkTheme; useEffect(() => { const timer = setTimeout(() => { setVideos(dummyData); }, 1000); return () => clearTimeout(timer); }, []);
if(!mountedComponent) return <div/>
return ( <ThemeProvider theme={themeMode}> <> <GlobalStyles/> <div className="App"> <Toggle theme={theme} toggleTheme={themeToggler} /> { videos.map((list, index) => { return ( <section key={index}> <h2 className="section-title">{list.section}</h2> <CardList list={list} /> <hr /> </section> ); })} </div> </> </ThemeProvider> ); }; export default App;
Am adăugat starea noastră mountedComponent
ca suport în cârligul useDarkMode
și am verificat dacă componenta noastră a fost montată, deoarece asta se întâmplă în cârligul useEffect
. Dacă nu s-a întâmplat încă, atunci vom reda un div
gol.
Să vedem rezultatul paginii noastre web în modul întunecat.
Acum, veți observa că în modul întunecat, când pagina se reîncarcă, culoarea butonului nu se schimbă.
Concluzie
Modul întunecat devine din ce în ce mai mult o preferință a utilizatorului, iar implementarea lui într-o aplicație web React este mult mai ușoară atunci când utilizați pachetul de tematică ThemeProvider
în componentele stilate. Continuați și experimentați cu componente cu stil în timp ce implementați modul întunecat; ai putea adauga pictograme in loc de buton.
Vă rugăm să împărtășiți feedback-ul și experiența dvs. cu funcția de tematică din componentele cu stil în secțiunea de comentarii de mai jos. Mi-ar plăcea să văd cu ce ai venit!
Depozitul de suport pentru acest articol este disponibil pe GitHub. De asemenea, verificați-l pe CodeSandbox.
Referințe
- „Documentare”, componente stilizate
- „Creați un mod întunecat al aplicației dvs. folosind Componente stilate”, Tom Nolan, Medium