Menerapkan Mode Gelap Dalam Aplikasi Bereaksi Menggunakan komponen gaya

Diterbitkan: 2022-03-10
Ringkasan cepat Mode cahaya adalah konvensi di sebagian besar aplikasi web dan seluler. Namun, dalam perkembangan modern, kita telah melihat bagaimana mode gelap, yang menampilkan teks terang dan elemen antarmuka pada latar belakang gelap, dengan cepat menjadi preferensi pengguna. Dalam artikel ini, kita akan belajar bagaimana menerapkan mode gelap secara efisien dalam aplikasi React pada halaman web sederhana, menggunakan library komponen bergaya dan memanfaatkan beberapa fitur React seperti hook. Kami juga akan membahas pro dan kontra dari mode gelap dan mengapa itu harus diadopsi.

Salah satu fitur perangkat lunak yang paling sering diminta adalah mode gelap (atau mode malam, sebagaimana orang lain menyebutnya). Kami melihat mode gelap di aplikasi yang kami gunakan setiap hari. Dari aplikasi seluler hingga web, mode gelap telah menjadi vital bagi perusahaan yang ingin menjaga mata penggunanya.

Mode gelap adalah fitur tambahan yang menampilkan sebagian besar permukaan gelap di UI. Sebagian besar perusahaan besar (seperti YouTube, Twitter, dan Netflix) telah mengadopsi mode gelap di aplikasi seluler dan web mereka.

Meskipun kita tidak akan membahas React dan komponen gaya secara mendalam, pengetahuan dasar tentang React, CSS, dan komponen gaya akan berguna. Tutorial ini akan bermanfaat bagi mereka yang ingin meningkatkan aplikasi web mereka dengan melayani mereka yang menyukai mode gelap.

StackOverflow mengumumkan mode gelap di Twitter
StackOverflow mengumumkan mode gelap di Twitter (Pratinjau besar)

Beberapa hari sebelum artikel ini ditulis, StackOverflow mengumumkan peluncuran mode gelapnya, yang memberi pengguna kesempatan untuk beralih di antara dua mode tersebut.

Mode gelap mengurangi ketegangan mata dan membantu saat Anda bekerja dalam waktu lama di komputer atau ponsel.

Apa itu Mode Gelap?

Mode gelap adalah skema warna antarmuka apa pun yang menampilkan teks terang dan elemen antarmuka pada latar belakang gelap, yang membuat layar sedikit lebih mudah dilihat di ponsel, tablet, dan komputer. Mode gelap mengurangi cahaya yang dipancarkan oleh layar, sambil mempertahankan rasio kontras warna minimum yang diperlukan untuk keterbacaan.

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

Mengapa Anda Harus Peduli Dengan Mode Gelap?

Mode gelap meningkatkan ergonomi visual dengan mengurangi ketegangan mata, menyesuaikan layar dengan kondisi cahaya saat ini, dan memberikan kemudahan penggunaan di malam hari atau di lingkungan yang gelap.

Sebelum menerapkan mode gelap di aplikasi kita, mari kita lihat manfaatnya.

Penghematan Baterai

Mode gelap di web dan aplikasi seluler dapat memperpanjang masa pakai baterai perangkat. Google telah mengkonfirmasi bahwa mode gelap pada layar OLED telah sangat membantu masa pakai baterai.

Misalnya, pada kecerahan 50%, mode gelap di aplikasi YouTube menghemat energi layar sekitar 15% lebih banyak daripada latar belakang putih datar. Pada kecerahan layar 100%, antarmuka gelap menghemat 60% energi layar.

Mode Gelap Itu Indah

Mode gelap itu indah, dan dapat meningkatkan daya tarik layar secara signifikan.

Sementara sebagian besar produk menginginkan tampilan putih lembut yang serupa, mode gelap menawarkan sesuatu yang berbeda yang terasa misterius dan baru.

Ini juga memberikan peluang besar untuk menyajikan konten grafis seperti dasbor, gambar, dan foto dengan cara yang segar.

Twitter mode gelap versus terang
Keindahan mode gelap Twitter di atas mode terang (Pratinjau besar)

Sekarang setelah Anda tahu mengapa Anda harus menerapkan mode gelap di aplikasi web berikutnya, mari selami komponen gaya, yang merupakan sumber daya penentu dari tutorial ini.

Mode gelap adalah skema warna antarmuka apa pun yang menampilkan teks terang dan elemen antarmuka pada latar belakang gelap, yang membuatnya sedikit lebih mudah dilihat di ponsel, tablet, dan komputer.

Apa itu komponen gaya?

Sepanjang artikel ini, kita akan sering menggunakan perpustakaan komponen gaya. Selalu ada banyak cara untuk mendesain aplikasi web modern. Ada metode penataan gaya tradisional di tingkat dokumen, yang mencakup pembuatan file index.css dan menautkannya ke HTML atau penataan gaya di dalam file HTML.

Banyak yang telah berubah dalam gaya aplikasi web baru-baru ini, sejak diperkenalkannya CSS-in-JS.

CSS-in-JS mengacu pada pola di mana CSS disusun menggunakan JavaScript. Ini menggunakan literal templat yang diberi tag untuk menata komponen dalam file JavaScript.

Untuk mempelajari lebih lanjut tentang CSS-in-JS, lihat artikel Anna Monus tentang masalah ini.

styled-components adalah pustaka CSS-in-JS yang memungkinkan Anda menggunakan semua fitur CSS yang Anda sukai, termasuk kueri media, pemilih semu, dan bersarang.

Mengapa komponen bergaya?

komponen gaya dibuat karena alasan berikut:

  • Tidak ada nama kelas sih
    Alih-alih Anda menggaruk-garuk kepala untuk menemukan nama kelas untuk sebuah elemen, komponen gaya menghasilkan nama kelas yang unik untuk gaya Anda. Anda tidak perlu khawatir tentang salah eja atau menggunakan nama kelas yang tidak memiliki arti.
  • Menggunakan alat peraga
    styled-components memungkinkan kita untuk memperluas properti styling menggunakan parameter props , yang biasa digunakan di React — dengan demikian, secara dinamis memengaruhi nuansa komponen melalui status aplikasi.
  • Mendukung sintaks Sass
    Menulis sintaks Sass di luar kotak tanpa harus menyiapkan praprosesor apa pun atau alat build tambahan dimungkinkan dengan komponen gaya. Dalam definisi gaya Anda, Anda dapat menggunakan karakter & untuk menargetkan komponen saat ini, menggunakan pemilih semu, dan bereksperimen dengan bersarang.
  • Bertema
    komponen-gaya memiliki dukungan tema penuh dengan mengekspor komponen pembungkus ThemeProvider . Komponen ini menyediakan tema untuk semua komponen React di dalam dirinya sendiri melalui Context API. Di pohon rendering, semua komponen bergaya akan memiliki akses ke tema yang disediakan, bahkan ketika mereka memiliki kedalaman beberapa level. Saat kita melanjutkan tutorial ini, kita akan melihat lebih dalam fitur tema komponen gaya.

Untuk mempelajari lebih lanjut keuntungan dari komponen gaya, lihat artikel Kris Guzman.

Menerapkan Mode Gelap

Pada artikel ini, kita akan menerapkan mode gelap pada halaman web sederhana seperti YouTube.

Untuk mengikuti, pastikan Anda mengkloning repositori asli dari cabang starter .

Pengaturan

Mari kita instal semua dependensi dalam file package.json kita. Dari terminal, jalankan perintah berikut:

 npm install

Setelah instalasi berhasil, jalankan npm start . Inilah tampilan halaman web tanpa mode gelap yang diterapkan di dalamnya.

Halaman web yang akan digunakan, tanpa mode gelap
Halaman web yang akan digunakan, tanpa mode gelap. (Pratinjau besar)

Untuk menginstal styled-components , di terminal Anda jalankan npm install styled-components .

Penerapan

Untuk menerapkan mode gelap, kita perlu membuat empat komponen berbeda.

  • Theme
    Ini berisi properti warna dari tema terang dan gelap kami.
  • GlobalStyles
    Ini berisi gaya global untuk seluruh dokumen.
  • Toggler
    Ini memegang elemen tombol yang mengaktifkan fungsionalitas.
  • useDarkMode
    Kait khusus ini menangani logika di balik perubahan tema dan persistensi tema kita di penyimpanan lokal.

Komponen Tema

Di folder src , Anda akan melihat komponen di folder components . Buat file Themes.js , dan tambahkan kode berikut ke dalamnya.

 export const lightTheme = { body: '#FFF', text: '#363537', toggleBorder: '#FFF', background: '#363537', } export const darkTheme = { body: '#363537', text: '#FAFAFA', toggleBorder: '#6B8096', background: '#999', }

Di sini, kami telah mendefinisikan dan mengekspor objek lightTheme dan darkTheme dengan variabel warna yang berbeda. Jangan ragu untuk bereksperimen dan menyesuaikan variabel yang sesuai dengan Anda.

komponen gaya global

Sisa di folder components Anda, buat file globalStyles.js , dan tambahkan kode berikut:

 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; } `

Kami telah mengimpor createGlobalStyle dari komponen gaya. Metode createGlobalStyle menggantikan metode injectGlobal yang sekarang tidak digunakan lagi dari komponen bergaya versi 3. Metode ini menghasilkan komponen React, yang, ketika ditambahkan ke pohon komponen Anda, akan menyuntikkan gaya global ke dalam dokumen, dalam kasus kami, App.js .

Kami mendefinisikan komponen GlobalStyle dan menetapkan background dan properti color ke nilai dari objek tema. Jadi, setiap kali kita mengganti tombol, nilainya akan berubah tergantung pada tema gelap atau objek tema terang yang kita lewati ke ThemeProvider (yang akan dibuat nanti, saat kita melanjutkan).

Properti transisi 0.50s memungkinkan perubahan ini terjadi sedikit lebih lancar, sehingga saat kita beralih bolak-balik, kita dapat melihat perubahan yang terjadi.

Membuat Fungsionalitas Beralih Tema

Untuk mengimplementasikan fungsi alih tema, kita hanya perlu menambahkan beberapa baris kode. Di file App.js , tambahkan kode berikut (perhatikan bahwa kode yang disorot adalah yang harus Anda tambahkan):

 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;

Kode yang disorot adalah yang baru ditambahkan ke App.js . Kami telah mengimpor ThemeProvider dari styled-components . ThemeProvider adalah komponen pembantu di perpustakaan komponen gaya yang menyediakan dukungan tema. Komponen pembantu ini menyuntikkan tema ke semua komponen Bereaksi di bawahnya sendiri melalui API Konteks.

Di pohon rendering, semua komponen bergaya akan memiliki akses ke tema yang disediakan, bahkan ketika mereka memiliki kedalaman beberapa level. Lihat bagian tentang "Tema".

Selanjutnya, kita mengimpor pembungkus GlobalStyle dari ./components/Globalstyle . Terakhir, dari atas, kita mengimpor objek lightTheme dan darkTheme dari ./components/Themes .

Agar kita dapat membuat metode toggling, kita memerlukan status yang menyimpan nilai warna awal tema kita. Jadi, kita membuat status theme , dan menyetel status awal ke light , menggunakan kait useState .

Sekarang, untuk fungsi toggling.

Metode themeToggler menggunakan operator ternary untuk memeriksa status theme , dan mengubah gelap atau terang berdasarkan nilai kondisinya.

ThemeProvider , komponen pembantu komponen gaya, membungkus semuanya dalam pernyataan return dan menyuntikkan komponen apa pun di bawahnya. Ingatlah bahwa GlobalStyles kami menyuntikkan gaya global ke dalam komponen kami; karenanya, ini disebut di dalam komponen pembungkus ThemeProvider .

Terakhir, kami membuat tombol dengan acara onClick yang menetapkan metode themeToggler kami untuk itu.

Mari kita lihat hasilnya sejauh ini.

Mode gelap diimplementasikan tanpa kegigihan.
Mode gelap diterapkan tanpa kegigihan (Pratinjau besar)

File App.js kami perlu difaktorkan ulang; banyak kode nya tidak KERING. (DRY adalah singkatan dari "jangan ulangi diri Anda sendiri", prinsip dasar pengembangan perangkat lunak yang bertujuan untuk mengurangi pengulangan.) Semua logika tampaknya ada di App.js ; itu praktik yang baik untuk memisahkan logika kita demi kejelasan. Jadi, kita akan membuat komponen yang menangani fungsi toggling.

Beralih Komponen

Masih di dalam folder components , buat file Toggler.js , dan tambahkan kode berikut ke dalamnya:

 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;

Untuk menjaga semuanya tetap rapi, kami telah mengatur gaya tombol sakelar kami di komponen Toggle , menggunakan fungsi styled dari komponen gaya.

Ini murni untuk presentasi; Anda dapat menata tombol sesuai keinginan Anda.

Di dalam komponen Toggle , kita melewati dua props:

  • theme menyediakan tema saat ini (terang atau gelap);
  • fungsi toggleTheme akan digunakan untuk beralih antar tema.

Selanjutnya, kita mengembalikan komponen Button dan menetapkan fungsi toggleTheme ke event onClick .

Terakhir, kami menggunakan propTypes untuk mendefinisikan tipe kami, memastikan bahwa theme kami adalah string dan isRequired , sementara toggleTheme kami adalah func dan isRequired .

Menggunakan Kait Kustom ( useDarkMode )

Saat membangun aplikasi, skalabilitas adalah yang terpenting, artinya logika bisnis kita harus dapat digunakan kembali, sehingga kita dapat menggunakannya di banyak tempat dan bahkan di proyek yang berbeda.

Itulah mengapa akan sangat bagus untuk memindahkan fungsi toggling kami ke komponen yang terpisah. Untuk itu, kami akan membuat kait khusus kami sendiri.

Mari buat file baru bernama useDarkMode.js di folder components , dan pindahkan logika kita ke file ini, dengan beberapa penyesuaian. Tambahkan kode berikut ke file:

 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] };

Kami telah menambahkan beberapa hal di sini.

  • setMode
    Kami menggunakan localStorage untuk bertahan di antara sesi di browser. Jadi, jika pengguna telah memilih tema gelap atau terang, itulah yang akan mereka dapatkan pada kunjungan berikutnya ke aplikasi atau jika mereka memuat ulang halaman. Oleh karena itu, fungsi ini menetapkan status kita dan meneruskan theme ke localStorage .
  • themeToggler
    Fungsi ini menggunakan operator ternary untuk memeriksa status tema dan beralih baik gelap atau terang berdasarkan kebenaran kondisi tersebut.
  • useEffect
    Kami telah menerapkan kait useEffect untuk memeriksa pemasangan komponen. Jika pengguna telah memilih tema sebelumnya, kami akan meneruskannya ke fungsi setTheme kami. Pada akhirnya, kami akan mengembalikan theme kami, yang berisi theme yang dipilih dan fungsi themeToggler untuk beralih antar mode.

Saya pikir Anda akan setuju bahwa komponen mode gelap kami terlihat ramping.

Mari menuju ke App.js untuk sentuhan akhir.

 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;

Kode yang disorot baru ditambahkan ke App.js .

Pertama, kami mengimpor kait khusus kami, merusak struktur theme dan alat peraga themeToggler , dan mengaturnya dengan fungsi useDarkMode .

Perhatikan bahwa metode useDarkMode menggantikan status theme kita, yang awalnya ada di App.js .

Kami mendeklarasikan variabel themeMode , yang merender tema terang atau gelap berdasarkan kondisi mode theme saat itu.

Sekarang, komponen pembungkus ThemeProvider kita diberikan variabel themeMode yang baru saja kita buat ke prop theme .

Dan terakhir, sebagai ganti tombol biasa, kami memasukkan komponen Toggle .

Ingat bahwa dalam komponen Toggle kami, kami mendefinisikan dan menata tombol dan meneruskan theme dan toggleTheme kepada mereka sebagai alat peraga. Jadi, yang harus kita lakukan adalah meneruskan props ini dengan tepat ke komponen Toggle , yang akan bertindak sebagai tombol kita di App.js .

Ya! Mode gelap kami disetel, dan tetap ada, tidak berubah warna saat halaman disegarkan atau dikunjungi di tab baru.

Mari kita lihat hasilnya dalam aksi:

Mode gelap diterapkan, tetapi dengan kesalahan pada warna tombol saat browser memuat ulang.
Mode gelap diterapkan, tetapi dengan kesalahan pada warna tombol saat browser memuat ulang. (Pratinjau besar)

Hampir semuanya bekerja dengan baik, tetapi ada satu hal kecil yang dapat kita lakukan untuk membuat pengalaman kita luar biasa. Beralih ke tema gelap lalu muat ulang halaman. Apakah Anda melihat bahwa warna biru pada tombol dimuat sebelum abu-abu untuk sesaat? Itu terjadi karena kait useState kami memulai tema light pada awalnya. Setelah itu, useEffect berjalan, periksa localStorage , dan baru kemudian setel theme ke dark . Mari lompat ke kait khusus useDarkMode.js dan tambahkan sedikit kode:

 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 ]
};

Kode yang disorot adalah satu-satunya yang ditambahkan ke useDarkMode.js . Kami telah membuat status lain bernama mountedComponent dan menyetel nilai default ke false menggunakan kait useState . Selanjutnya, di dalam kait useEffect , kami mengatur status mountedComponent menjadi true menggunakan setMountedComponent . Terakhir, dalam array return , kami menyertakan status mountedComponent .

Terakhir, mari tambahkan sedikit kode di App.js agar semuanya berfungsi.

 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;

Kami telah menambahkan status mountedComponent kami sebagai penyangga di kait useDarkMode kami, dan kami telah memeriksa apakah komponen kami telah dipasang, karena inilah yang terjadi di kait useEffect . Jika belum terjadi, maka kita akan membuat div kosong.

Mari kita lihat hasil halaman web mode gelap kita.

Hasil akhir dari mode gelap
Hasil akhir dari mode gelap (Pratinjau besar)

Sekarang, Anda akan melihat bahwa saat dalam mode gelap, saat halaman dimuat ulang, warna tombol tidak berubah.

Kesimpulan

Mode gelap semakin menjadi preferensi pengguna, dan mengimplementasikannya dalam aplikasi web React jauh lebih mudah saat menggunakan pembungkus tema ThemeProvider di komponen bergaya. Silakan bereksperimen dengan komponen gaya saat Anda menerapkan mode gelap; Anda dapat menambahkan ikon alih-alih tombol.

Silakan bagikan umpan balik dan pengalaman Anda dengan fitur tema dalam komponen bergaya di bagian komentar di bawah. Saya ingin melihat apa yang Anda dapatkan!

Repositori pendukung untuk artikel ini tersedia di GitHub. Juga, periksa di CodeSandbox.

Referensi

  • "Dokumentasi", komponen gaya
  • “Buat Mode Gelap aplikasi Anda menggunakan Komponen Bergaya”, Tom Nolan, Medium