Hamburger Menü mit einer Seite Reagieren Hooks und Stil-Komponenten

0
7

Wir alle wissen, was ein hamburger-Menü, richtig? Wenn das Muster begann seinen Weg in web-designs, war es den beiden verspottet und Beifall für seine Minimalismus, der es ermöglicht Haupt-Menüs versteckt werden, Weg vom Schirm, vor allem auf mobile, wo jeder pixel von Raum zählt.

CSS-Tricks ist alles etwa doppelt Fleisch.

Liebe ‘em oder Hass ‘em, hamburger-Menüs sind hier und wird wahrscheinlich für einige Zeit zu kommen. Das problem ist, wie man diese umsetzen kann. Sicher, Sie suchen einfach und unkompliziert, aber Sie können alles sein, aber. Zum Beispiel, sollten Sie zusammen mit einem label? Sind Sie wirksamer auf der linken oder rechten Seite des Bildschirms? Wie schaffen wir schließen den Menüs, ob durch klicken oder berühren? Sollte das Symbol sein, eine SVG, die schriftart, die Unicode-Zeichen oder reinem CSS? Was ist eine fleischlose option?

Ich wollte bauen, aber nicht finden eine einfache Lösung. Die meisten Lösungen basieren auf Bibliotheken, wie reactjs-popup oder reagieren-burger-Menü. Sie sind groß, aber für komplexere Lösungen. Was ist der Kern-Anwendungsfall für ein drei-line-Menü, dass die Folien einfach ein panel aus der Seite des Bildschirms, wenn es angeklickt wird, dann schiebt das panel zurück, wenn es wieder geklickt?

Ich beschloss, meine eigenen bauen, einfachen hamburger mit sidebar. Keine Essiggurken, Zwiebeln und ketchup. Nur Fleisch, Brötchen, und eine Seite der Menüpunkte.

Sind Sie bereit, erstellen Sie es mit mir?

Blick auf CodePen Blick auf GitHub

Hier ist, was wir machen

Siehe Stift
Burger-Menü mit Reagieren hooks und Stil-Komponenten von Maks Akymenko (@maximakymenko)
auf CodePen.

Wir bauen verwenden Sie Reagieren für dieses tutorial, weil es scheint wie eine gute Verwendung für Sie: wir erhalten eine wiederverwendbare Komponente und eine Reihe von Haken, die wir erweitern können, um Griff-click-Funktionalität.

Spin up, ein neues Projekt Reagieren

Let ‘ s spin-up-ein neues Projekt mithilfe von create-reagieren-app, wechseln Sie zu diesem Ordner, und fügen Sie Stil-Komponenten zum Stil der Benutzeroberfläche:

npx erstellen-reagieren-app-Ihr-Projekt-name
cd Ihr-Projekt-name
Garn, hinzufügen von Stil-Komponenten

Hinzufügen von grundlegenden Stile

Öffnen Sie die neu erstellte Projekt in Ihrem Lieblings-code-editor, und starten Sie das hinzufügen von basic-styles mit Stil-Komponenten. In deinem src-Verzeichnis, erstellen Sie eine Datei namens global.js. Es enthält die Stile für die ganze app. Sie können Ihre eigenen schreiben oder einfach nur kopieren, was ich am Ende machen:

// global.js
import { createGlobalStyle } von ‘Stil-Komponenten’;

export const GlobalStyles = createGlobalStyle`
html, body {
margin: 0;
padding: 0;
}
*, *::nach *::before {
box-sizing: border-box;
}
body {
align-items: center;
background: #0D0C1D;
color: #EFFFFA;
display: flex;
font-family: apple-system, BlinkMacSystemFont, “Segoe UI”, Roboto, Helvetica, Arial, sans-serif “Apple Color Emoji”, “Segoe UI Emoji”, “Segoe UI Symbol”;
height: 100vh;
justify-content: center;
text-rendering: optimizeLegibility;
}
`

Dies ist nur ein Teil der globalen Stile, den rest finden Sie hier.

Die CreateGlobalStyle Funktion wird im Allgemeinen verwendet für die Erstellung von globalen Stilen, die verfügbar gemacht werden, um die gesamte app. Wir importieren es, also haben wir den Zugang zu diesen styles als wir gehen.

Der nächste Schritt ist das hinzufügen eine Design-Datei enthält alle Variablen. Erstellen Sie eine theme.js Datei im src-Verzeichnis und fügen Sie die folgende:

// theme.js
export const theme = {
primaryDark: ‘#0D0C1D’,
primaryLight: ‘#EFFFFA’,
primaryHover: ‘#343078’,
mobile: ‘576px’,
}

Hinzufügen von layout, Menü und hamburger Komponenten 🍔

Gehen Sie zu Ihrem App.js Datei. Wir wischen alles aus, und erstellen Sie die Hauptvorlage für unsere app. Hier ist, was ich Tat. Sie können sicherlich erstellen Sie Ihre eigenen.

// App.js
importieren Reagieren von ‘reagieren’;
import { ThemeProvider } von ‘Stil-Komponenten’;
import { GlobalStyles } from ‘./global’;
import { Thema } from ‘./Thema’;

Funktion App() {
return (
<ThemeProvider theme={Thema}>
<>
<GlobalStyles />
<div>
<h1>Hallo. Dies ist burger-Menü-tutorial</h1>
<img src=”https://image.flaticon.com/icons/svg/2016/2016012.svg” alt=”burger-icon” />
<small>Icon made by Freepik from www.flaticon.com</small>
</div>
</>
</ThemeProvider>
);
}
export Standard-App;

Vergessen Sie nicht, fügen Sie die Zeile mit dem kleinen tag. Das ist, wie wir Kredit flaticon.comhttp://flaticon.com -) Autoren für die zur Verfügung gestellten Symbol.

Hier ist, was wir haben, bis zu diesem Punkt:

Lassen Sie mich erklären ein wenig. Wir importierten ThemeProvider, das ist ein wrapper-Komponente, die verwendet die Kontext-API hinter den kulissen, um unsere Design-Variablen zur Verfügung, um die gesamte Komponente Baum.

Wir haben auch importierte unsere GlobalStyles und übergeben Sie Sie als eine Komponente zu unserer app, was bedeutet, dass unsere Anwendung hat nun Zugriff auf alle globalen Stilen. Wie Sie sehen können, unsere GlobalStyles Komponente in ThemeProvider was bedeutet, können wir bereits einige kleinere änderungen.

Gehen Sie zu global.js und ändern Sie die hintergrund-und Farb-Eigenschaften, die unsere definierten Variablen. Dies hilft uns bei der Umsetzung ein Thema, eher als die Verwendung von festen Werten, die nur schwer zu ändern sind.

// global.js
hintergrund: ${({ Thema }) => Thema.primaryDark};
Farbe: ${({ Thema }) => Thema.primaryLight};

Wir destructure unser Thema von Requisiten. Also, anstatt zu schreiben, Requisiten.Thema jedes mal sind wir mit einer Reihe von Klammern statt. Ich wiederhole mich: das Thema zur Verfügung stehen, da haben wir gewickelt unseren globalen Stile mit ThemeProvider.

Erstellen Sie Burger und Menü-Komponenten

Erstellen Sie ein Komponenten-Ordner in den src-Verzeichnis und fügen Sie zwei Ordner drin: Menü und Burger, sowie eine index.js Datei.

index.js wird verwendet für einen Zweck: Sie ermöglichen uns den import von Komponenten aus einer Datei, die ist sehr praktisch, vor allem, wenn Sie haben eine Menge von Ihnen.

Jetzt erstellen wir unsere Komponenten. Jeder Ordner enthält drei Dateien.

Was ist mit den ganzen Dateien? Sie sehen den Vorteil einer skalierbaren Struktur bald genug. Es funktionierte gut für mich in ein paar Projekten, aber hier ist ein guter Rat, wie man erstellen Sie skalierbare Struktur.

Gehen Sie auf die Burger-Ordner und erstellen Burger.js für unser layout. Dann fügen Sie Burger.styled.js, die Stile enthalten, und index.js. wird die Datei exportieren.

// index.js
export { default } from ‘./Burger’;

Fühlen Sie sich frei, um style burger Knebel in einer Weise, die Sie möchten, oder fügen Sie diese Stile:

// Burger.styled.js
importieren Stil von ‘Stil-Komponenten’;

export const StyledBurger = gestylt.- Taste`
position: absolute;
top: 5%;
Links: 2rem;
display: flex;
flex-direction: column;
justify-content: space-around;
Breite: 2rem;
Höhe: 2rem;
hintergrund: transparent;
border: none;
cursor: pointer;
padding: 0;
z-index: 10;

&:focus {
outline: none;
}

div {
Breite: 2rem;
Höhe: 0.25 rem;
hintergrund: ${({ Thema }) => Thema.primaryLight};
border-radius: 10px;
transition: all 0.3 s linear;
position: relative;
transform-origin: 1px;
}
`;

Die transform-origin-Eigenschaft wird später benötigt, um zu animieren, das Menü wechselt zwischen offenen und geschlossenen Zuständen.

Nach dem hinzufügen der Stile, um Burger.js und fügen Sie das layout:

// Burger.js
importieren Reagieren von ‘reagieren’;
import { StyledBurger } from ‘./Burger.Stil’;

const Burger = () => {
return (
<StyledBurger>
<div />
<div />
<div />
</StyledBurger>
)
}

export Standard-Burger;

Danach suchen Sie in der linken oberen Ecke. Sehen Sie es?

Zeit, das gleiche zu tun mit den Menü-Ordner:

// Menü -> index.js
export { default } from ‘./Menu’;

// Menu.styled.js
importieren Stil von ‘Stil-Komponenten’;

export const StyledMenu = gestylt.nav`
display: flex;
flex-direction: column;
justify-content: center;
hintergrund: ${({ Thema }) => Thema.primaryLight};
height: 100vh;
text-align: left;
Polsterung: 2rem;
position: absolute;
top: 0;
left: 0;
transition: transform 0.3 s ease-in-out;

@media (max-width: ${({ Thema }) => Thema.mobile}) {
width: 100%;
}

a {
font-size: 2rem;
text-transform: Großbuchstaben;
Polsterung: 2rem 0;
font-weight: bold;
letter-spacing: 0.5 rem;
Farbe: ${({ Thema }) => Thema.primaryDark};
text-decoration: none;
transition: color 0.3 s linear;

@media (max-width: ${({ Thema }) => Thema.mobile}) {
font-size: 1.5 rem;
text-align: center;
}

&:hover {
Farbe: ${({ Thema }) => Thema.primaryHover};
}
}
`;

Als Nächstes fügen wir das layout für die Menü-Elemente aufgedeckt werden, die beim Klick auf unsere burger:

// Menu.js
importieren Reagieren von ‘reagieren’;
import { StyledMenu } from ‘./Menü.Stil’;

const-Menü = () => {
return (
<StyledMenu>
<a href=”/”>
<span role=”img” aria-label=”über uns”>&#x1f481;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;</span>
Wir über uns
</a>
<a href=”/”>
<span role=”img” aria-label=”Preis”>&#x1f4b8;</span>
Preise
</a>
<a href=”/”>
<span role=”img” aria-label=”Kontakt”>&#x1f4e9;</span>
Kontakt
</a>
</StyledMenu>
)
}
export-Standard-Menü;

Wir haben nette emojis hier, und best-Praxis zugänglich zu machen, indem er jeden in einen span und das hinzufügen von ein paar Eigenschaften: role=”img” und aria-label=”dein label”. Sie können mehr darüber Lesen Sie hier.

Zeitpunkt der Einfuhr unser neuer Komponenten in unsere App.js Datei:

// App.js
importieren Reagieren von ‘reagieren’;
import { ThemeProvider } von ‘Stil-Komponenten’;
import { GlobalStyles } from ‘./global’;
import { Thema } from ‘./Thema’;
import { Burger, Menü } from ‘./Komponenten’;

// …

Mal sehen, was wir haben:

Werfen Sie einen Blick auf diese nette Navigationsleiste! Aber wir haben ein Problem hier: es ist geöffnet, und wir wollen es zunächst geschlossen werden. Wir müssen nur hinzufügen, eine Zeile zu Menu.styled.js fix it:

// Menu.styled.js
transformieren: ‘translateX(-100%)’;

Wir sind gut auf unserem Weg zum aufrufen dieser burger zubereitet! Aber zuerst…

Hinzufügen, öffnen und schließen-Funktionalität

Wir möchten offen sein für die sidebar beim Klick auf das hamburger-Symbol, also lasst uns um es zu bekommen. Öffnen App.js und fügen Sie einige Staat zu. Wir verwenden die useState Haken für Sie.

// App.js
importieren Reagieren, { useState } von ‘reagieren’;

Nachdem Sie Sie importiert haben, verwenden Sie es in der App-Komponente.

// App.js
const [öffnen, setOpen] = useState(false);

Wir stellen den ursprünglichen Zustand auf false, weil unser Menü ausgeblendet werden soll, wenn die Anwendung gerendert wird.

Wir müssen beide unsere Knebel und sidebar-Menü, um wissen über den Zustand, so übergeben Sie es nach unten, die als requisite für jede einzelne Komponente. Jetzt Ihre App.js sollte in etwa so Aussehen:

// App.js
importieren Reagieren, { useState } von ‘reagieren’;
import { ThemeProvider } von ‘Stil-Komponenten’;
import { GlobalStyles } from ‘./global’;
import { Thema } from ‘./Thema’;
import { Burger, Menü } from ‘./Komponenten’;

Funktion App() {
const [öffnen, setOpen] = useState(false);
return (
<ThemeProvider theme={Thema}>
<>
<GlobalStyles />
<div>
<h1>Hallo. Dies ist burger-Menü-tutorial</h1>
<img src=”https://media.giphy.com/media/xTiTnwj1LUAw0RAfiU/giphy.gif” alt=”animierte-burger” />
</div>
<div>
<Burger open={öffnen} setOpen={setOpen} />
<- Menü öffnen={öffnen} setOpen={setOpen} />
</div>
</>
</ThemeProvider>
);
}
export Standard-App;

Beachten Sie, dass wir Verpacken unserer Komponenten in einem div. Dies wird später hilfreich sein, wenn wir hinzufügen, die Funktionalität, das Menü wird geschlossen, wenn Sie auf eine beliebige Stelle auf dem Bildschirm.

Griff Requisiten in die Komponenten

Unsere Burger und Menü-wissen über den Zustand, also alles, was wir tun müssen, ist, es zu handhaben innen und fügen Sie Stile hinzu, entsprechend. Gehen Sie zu Burger.js und kümmern sich um die Requisiten, die wurden weitergegeben:

// Burger.js
importieren Reagieren von ‘reagieren’;
import { bool func } von prop-Typen’;
import { StyledBurger } from ‘./Burger.Stil’;
const Burger = ({ öffnen, setOpen }) => {
return (
<StyledBurger open={öffnen} onClick={() => setOpen(!offen)}>
<div />
<div />
<div />
</StyledBurger>
)
}
Burger.propTypes = {
open: bool.isRequired,
setOpen: func.isRequired,
};
export Standard-Burger;

Wir destructure das öffnen und setOpen Requisiten und übergeben Sie an unsere StyledBurger zum hinzufügen von Stilen für jeden prop, beziehungsweise. Auch wir fügen Sie der onClick-handler aufrufen, unsere setOpen Funktion und wechseln öffnen prop. Am Ende der Datei fügen wir die Typ-Prüfung, die als best practice für die Anordnung der Argumente mit den erwarteten Daten.

Sie können überprüfen, ob es funktioniert oder nicht, indem Sie zur reagieren-dev-tools. Gehen Sie auf Komponenten-tab in Ihrem Chrome-DevTools und klicken Sie auf Burger tab.

Nun, wenn Sie auf Ihre Burger-Komponente, (nicht zu verwechseln mit dem Reiter), die Sie sehen sollten, dass Sie Ihre Kontrollkästchen öffnen wird, seinen Zustand zu ändern.

Gehen Sie zu Menu.js und fast die gleichen, obwohl, hier passieren wir nur die open-prop:

// Menu.js
importieren Reagieren von ‘reagieren’;
import { bool } von prop-Typen’;
import { StyledMenu } from ‘./Menü.Stil’;
const-Menü = ({ offen }) => {
return (
<StyledMenu open={open}>
<a href=”/”>
<span role=”img” aria-label=”über uns”>&#x1f481;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;</span>
Wir über uns
</a>
<a href=”/”>
<span role=”img” aria-label=”Preis”>&#x1f4b8;</span>
Preise
</a>
<a href=”/”>
<span role=”img” aria-label=”Kontakt”>&#x1f4e9;</span>
Kontakt
</a>
</StyledMenu>
)
}
Menü.propTypes = {
open: bool.isRequired,
}
export-Standard-Menü;

Der nächste Schritt ist, zu übergeben, öffnen prop auf unsere Stil-Komponente so konnten wir den übergang anwenden. Öffnen Menu.styled.js und fügen Sie den folgenden, um unsere transform-Eigenschaft:

transformieren: ${({ offen }) => offen ? ‘translateX(0)’ : ‘translateX(-100%)’};

Dies ist die Prüfung, ob unser Stil-Komponente öffnen prop wahr ist, und wenn ja, fügt es translateX(0) verschieben die navigation wieder auf den Bildschirm. Schon können Sie testen Sie es vor Ort!

Warten, warten, warten!

Haben Sie bemerkt, dass etwas falsch ist, wenn die Dinge heraus zu überprüfen? Unsere Burger hat die gleiche Farbe wie die Hintergrundfarbe von unserer Speisekarte, die Sie miteinander verbinden. Lasst uns das ändern und auch das Symbol animieren ein bisschen um es interessanter zu machen. Wir haben die open-prop übergeben, so dass wir verwenden können, um die änderungen zu übernehmen.

Öffnen Burger.styled.js und das folgende schreiben:

// Burger.styled.js
importieren Stil von ‘Stil-Komponenten’;
export const StyledBurger = gestylt.- Taste`
position: absolute;
top: 5%;
Links: 2rem;
display: flex;
flex-direction: column;
justify-content: space-around;
Breite: 2rem;
Höhe: 2rem;
hintergrund: transparent;
border: none;
cursor: pointer;
padding: 0;
z-index: 10;

&:focus {
outline: none;
}

div {
Breite: 2rem;
Höhe: 0.25 rem;
hintergrund: ${({ theme, open }) => öffnen ? Thema.primaryDark : Thema.primaryLight};
border-radius: 10px;
transition: all 0.3 s linear;
position: relative;
transform-origin: 1px;

:first-child {
transformieren: ${({ offen }) => öffnen ? ” rotate(45deg)’ : ‘rotate(0)’};
}

:nth-child(2) {
Deckkraft: ${({ offen }) => öffnen ? ‘0’ : ‘1’};
transformieren: ${({ offen }) => offen ? ‘translateX(20px)’ : ‘translateX(0)’};
}

:nth-child(3) {
transformieren: ${({ offen }) => offen ? ‘rotate(-45deg)’ : ‘rotate(0)’};
}
}
`;

Dies ist ein großer Teil von CSS, aber das macht die animation Magie geschehen. Wir prüfen, ob der prop ist wahr und Stile ändern sich entsprechend. Wir drehen, übersetzen, dann ausblenden des Menü-symbols Linien, während die Farbe zu ändern. Schön, nicht wahr?

Okay, Leute! Sie sollten inzwischen wissen, wie Sie eine einfache hamburger-icon und Menü, das beinhaltet das Reaktionsvermögen und flüssige Animationen. Herzlichen Glückwunsch!

Aber es gibt eine Letzte Sache, die wir sollten Konto für…

Das Menü schließen, indem Sie außerhalb der it

Dieser Teil scheint wie ein kleiner bonus, aber es ist ein großer UX gewinnen, weil es ermöglicht dem Benutzer, um das Menü zu schließen, indem Sie irgendwo anders auf der Seite. Dies hilft dem Benutzer zu vermeiden, zu re-suchen Sie das Menü-Symbol und klicken Sie genau auf es.

Wir werden noch mehr Reagieren, Haken zu verwenden, um dies möglich zu machen! Erstellen Sie eine Datei im src-Verzeichnis aufgerufen hooks.js und öffnen Sie es. Für diese, wir sind gonna wiederum zu den useEffect Haken, die eingeführt wurde, Reagieren 18.

// hooks.js
import { useEffect } von ‘reagieren’;

Bevor wir den code schreiben, müssen wir uns Gedanken über die Logik hinter diesem Haken. Wenn wir klicken irgendwo auf der Seite, die wir brauchen, um zu überprüfen, ob die angeklickte element ist unsere aktuelle element (in unserem Fall ist das die Menu-Komponente) oder wenn das angeklickte element mit dem aktuellen element (für Beispiel, unser div-Element umschließt, die unsere Menü-und hamburger-Symbol). Wenn dem so ist, wissen wir nicht nichts tun, sonst werden wir eine Funktion aufrufen, dass wir den Namen handler.

Gehen wir der ref zu überprüfen, wird der angeklickte element, und wir werden dies tun, jedes mal, wenn jemand Klicks auf die Seite.

// hooks.js
import { useEffect } von ‘reagieren’;

export const useOnClickOutside = (ref, – handler) => {
useEffect(() => {
const listener = Ereignis => {
if (!ref.Strom || ref.aktuelle.enthält(event.Ziel)) {
return;
}
handler(Ereignis);
};
Dokument.addEventListener(‘mousedown’, listener);
return () => {
Dokument.removeEventListener(‘mousedown’, listener);
};
},
[ref -, hf],
);
};

Vergessen Sie nicht, um zurückzukehren die Funktion von useEffect. Das so genannte “clean up”, und im Grunde genommen, steht es für das entfernen eines Ereignis-listener bei der Komponente hebt. Es ist der Ersatz von componentWillUnmount Lebenszyklus.

Lassen Sie uns nun Haken Sie die Haken

Wir haben unsere Haken bereit, so ist es Zeit, um es in die app. Gehen Sie auf die App.js Datei, und importieren Sie zwei Haken: die neu erstellte useOnClickOutside und auch useRef. Wir brauchen letztere, um einen Verweis auf das element.

// App.js
importieren Reagieren, { useState, useRef } von ‘reagieren’;
import { useOnClickOutside } from ‘./Haken’;

Um Zugriff zu erhalten, diese in das aktuelle element, das wir brauchen, um Zugriff auf die DOM-Knoten. Das ist, wo wir useRef, auch der name-Knoten, perfekt spiegelt die Stelle dieser Variablen.

Von dort aus passieren wir die Knoten als erstes argument. Wir passieren die Funktion, schließt sich unsere Speisekarte als zweites argument.

// App.js
const node = useRef();
useOnClickOutside(Knoten, () => setOpen(false));

Schließlich müssen wir geben unser ref für das DOM-element. In unserem Fall, es werden div, das hält den Burger-und Menu-Komponenten:

// App.js
<div ref={node}>
<Burger open={öffnen} setOpen={setOpen} />
<- Menü öffnen={öffnen} setOpen={setOpen} />
</div>

Ihre App.js sollte ähnlich wie dieses Aussehen:

// App.js
importieren Reagieren, { useState, useRef } von ‘reagieren’;
import { ThemeProvider } von ‘Stil-Komponenten’;
import { useOnClickOutside } from ‘./Haken’;
import { GlobalStyles } from ‘./global’;
import { Thema } from ‘./Thema’;
import { Burger, Menü } from ‘./Komponenten’;
Funktion App() {
const [öffnen, setOpen] = useState(false);
const node = useRef();
useOnClickOutside(Knoten, () => setOpen(false));
return (
<ThemeProvider theme={Thema}>
<>
<GlobalStyles />
<div>
<h1>Hallo. Dies ist burger-Menü-tutorial</h1>
<img src=”https://media.giphy.com/media/xTiTnwj1LUAw0RAfiU/giphy.gif” alt=”animierte-burger” />
</div>
<div ref={node}>
<Burger open={öffnen} setOpen={setOpen} />
<- Menü öffnen={öffnen} setOpen={setOpen} />
</div>
</>
</ThemeProvider>
);
}
export Standard-App;

Check this out! Es funktioniert wie erwartet, und es ist voll funktionsfähig und reagieren.

Herzlichen Glückwunsch, an alle! Sie hat einen tollen job! Happy coding!

Blick auf GitHub