Skip to content

Wie ich mit Theme UI meine Gatsby Themes Bibliothek gebaut habe

25.07.20195 Min. LesezeitKategorie: Coding

Themes für Gatsby zu erstellen macht Spaß und ist eine gute Möglichkeit, Projekte mit der Open Source Community zu teilen. In der Vergangenheit habe ich hauptsächlich Starter erstellt, die ich in die Starterübersicht auf Gatsbyjs.org eingereicht habe und damit quasi fertig war. Während ich daran arbeitete meinen ersten Starter zu einem Theme zu konvertieren, wurde mir klar, dass ich keine gute Übersicht oder Marketingseite für meine Starter habe - das wollte ich für meine kommenden Themes ändern! Deshalb habe ich themes.lekoarts.de erstellt. Es zeigt derzeit meine verfügbaren Themes und deren jeweilige Links zu GitHub und Demo-Website. Außerdem plane ich, jeden Monat einen Newsletter zu versenden, also abonniere ihn :)

Mit diesem Blogpost möchte ich den Prozess der Erstellung meiner Gatsby Themes Bibliotheks-Website mit Theme UI beschreiben. Ich werde nicht zu tief in die technischen Details einsteigen, also erwarte bitte nicht, dass dies ein Tutorial ist.

#Design

Fast jedes Mal, bevor ich mit der Programmierung eines Projekts beginne, beginne ich mit dem Design in Figma. Ich bin beim Prototyping mit Figma noch schneller als im Code mit React (wahrscheinlich aufgrund meines Designhintergrundes). Ich fing an, mir Dribbble und Behance anzusehen, um etwas Inspiration zu finden, da ich eine helle Website mit verspielten Elementen, einer atemberaubenden Hero-Sektion und ansonsten minimalem Design im Sinn hatte.

Mir hat der prominente und auffordernde Hero-Bereich der Refactoring UI Website sehr gut gefallen, die Formen und Farben der anderen Designs. Apropos Refactoring UI: Für das Design (und später für die Programmierung) habe ich die TailwindCSS Farben und Stile verwendet.

Das Design, das du jetzt live auf der Website siehst, ist so ziemlich das Design, das ich in Figma erstellt habe - was für die einfache Handhabung eines Figma (+ TailwindCSS-Stile) => Theme UI (+ TailwindCSS-Preset) Workflows spricht!

Wie bereits erwähnt, wollte ich auch eine geniale Hero-Sektion, nichts Langweiliges, aber auch nichts, was überstrapaziert wird (und möglicherweise auch die Website verlangsamen kann), wie particles.js. Da ich mit Cinema4D und 3D im Allgemeinen ziemlich gut bin, habe ich nur versucht, "Gatsby Themes" mit 3D-Modellen zu visualisieren. Ich habe mich von Kyle Gills Illustrationen inspirieren lassen. Ich habe die Szene mit Arnold gerendert, mit Photoshop bearbeitet und et voilá: So siehst das fertige Bild aus:

#Code

Die Website befindet sich im www-Ordner des Monorepo und ist daher bereits für die Verwendung mit TypeScript eingerichtet. Du kannst einen Blick auf den Quellcode werfen, um zu sehen, wie es gemacht wird (da es etwas langweilig wäre, den kompletten Code durchzugehen....). Ein nachfolgender Blogbeitrag wird erklären, wie ich das 3D-Element im Hero-Bereich erstellt habe.

Ich möchte mich auf Theme UI konzentrieren und erklären, wie ich es auf dieser Landing Page verwendet habe, insbesondere die Breakpoints-Syntax, Variants und das Tailwind-Preset. Das sind für mich echte Game Changer!

Um loszulegen, habe ich das Preset installiert und in meine Theme UI Konfiguration eingefügt (siehe offizielle Dokumentation dazu). Dann musste ich die Farben überschreiben, z.B. die Primär- und Sekundärfarbe. Dazu habe ich mir mein Figma-Design angesehen:

Es ist toll, an allen Stellen die gleichen Design-Tokens zu haben. Ich wählte die Farbe Indigo.600 und später in Theme UI musste ich nur noch die folgende Farbe verwenden colors.indigo[6].

#Variants

Die Unteransicht von VS Code zeigt einen Ausschnitt aus den Button-Varianten - Varianten sind eine Themen UI-Funktion (siehe Dokumentation). Ich habe sie für die Buttons und Farbverläufe verwendet. Letzteres sieht in etwa so aus:

src/gatsby-plugin-theme-ui/index.js
gradients: {
  blue: {
    backgroundImage: t => `linear-gradient(45deg, ${t.colors.indigo[3]}, ${t.colors.indigo[5]})`,
  },
},

Du kannst mit einer Funktion, die ich in diesem Fall gemacht habe, auf Theme-Werte zugreifen, um deine bereits definierten Farben in den Verläufen verwenden zu können. Warum habe ich also die Verlauf-Variants eingerichtet? Ich wollte eine einzelne Property in meiner Komponente "Shapes" verwenden, um die Farbe zu definieren. Ich habe nicht einfach den Wert in der Komponente selbst wie backgroundImage:t=>`linear-gradient(135deg,${t.colors[colorProp][8]},${t.colors[colorProp][6]})` übergeben, weil dann jede Form den gleichen Winkel und den gleichen Abstand gehabt hätte (hier Wert 8 und 6). Einige Farben benötigen andere Werte, um richtig auszusehen, so dass Variants hier die einzig logische Wahl waren. Die Verwendung sieht in etwa so aus:

const Circle = ({ color, className }) => (
  <div
    sx={{
      variant: `gradients.${color}`,
    }}
    className={className}
  />
)

Kleiner Tipp: Wenn du className durchreichst, kannst du die Komponenten von außen stylen.

#Breakpoints

Während die Formen (Kreis, Donut, Gitter) auf größeren Displays wirklich gut aussehen, müssen für Mobil- und Tablett-Ansichten die ursprüngliche Größe und Position angepasst werden. Ich bin immer noch ein Fan von "form follows function", also sollten sie beim Lesen nicht im Weg stehen. Wenn Du dir den Quellcode für den Hero-Bereich ansiehst, wirst du feststellen, dass es sehr intuitiv ist, diese Eigenschaften zu definieren:

<Circle
  size="210px"
  color="orange"
  top="170px"
  left={[`-185px`, `-185px`, `-185px`, `-120px`]}
  sx={{ display: [`none`, `none`, `none`, `block`] }}
/>

Ich emppfehle es sehr die Breakpoint-Syntax zu nutzen und die Documentation zu lesen.

So weit, so normal. Aber ich hatte eine coole Idee, mein Problem der Positionierung von Formen um meine Themeneinträge herum zu lösen, die ich in einer.yaml-Datei sammle (siehe Quelldatei). Definiere einfach die Formen im jeweiligen Themeneintrag! YAML ist ein großartiges Format dafür, da es (zusammen mit dem Gatsby-Transformator) die Erstellung von Arrays und Arrays von Objekten ermöglicht. Der Shapes-Eintrag sieht so aus:

shapes: [
  {
    type: "circle",
    color: "green",
    size: ["200px", "300px"],
    xOffset: ["-140px", "-120px"],
    yOffset: ["-70px"],
    opacity: 0.5,
  },
  {
    type: "donut",
    color: "teal",
    size: ["25px", "100px"],
    xOffset: ["50px"],
    yOffset: ["-60px"],
    opacity: 1,
  },
]

Das sind alle Informationen, die meine Formkomponenten benötigen, um die gewünschte Leistung zu erbringen. Ich habe hier nicht "left" und "right" verwendet, da die Formen immer nach außen zeigen sollten (auf der Innenseite könnte es den Text überlappen). Wie du sehen kannst, wurde die Array / Breakpoints Notation für Position und Größe verwendet - ich denke, das ist einfach cool 😎

Um dir eine Vorstellung davon zu geben, wie ich diese Funktionalität dann in die Homepage aufgenommen habe, hier ein Auszug aus der entsprechenden Datei:

src/components/listing.tsx
<Container sx={{ py: 4 }}>
  {themes.map((theme, index) => {
    const isEven = index % 2 === 0

    return (
      <Box>
        <div>
          {theme.shapes.map(shape => {
            switch (shape.type) {
              case `circle`:
                return (
                  <Circle
                    key={`${shape.size}-${shape.color}-${shape.xOffset}`}
                    size={shape.size}
                    color={shape.color}
                    left={isEven ? shape.xOffset : `unset`}
                    right={isEven ? `unset` : shape.xOffset}
                    top={shape.yOffset}
                    sx={{ zIndex: 0, opacity: shape.opacity }}
                  />
                )
              case `donut`:
                return (
                  <Donut
                    key={`${shape.size}-${shape.color}-${shape.xOffset}`}
                    width="20px"
                    size={shape.size}
                    color={shape.color}
                    left={isEven ? shape.xOffset : `unset`}
                    right={isEven ? `unset` : shape.xOffset}
                    top={shape.yOffset}
                    sx={{ zIndex: 0, opacity: shape.opacity }}
                  />
                )
              default:
                return null
            }
          })}
        </div>
      </Box>
    )
  })}
</Container>

Das Setzen der Offsetwerte auf links oder rechts wird von isEven entschieden, was auch dazu dient, die Reihenfolge der Elemente zu ändern. Das Einbringen der Arrays in die Properties funktioniert wie auf dem Rest der Seite und damit das Responsive Styling!

#Fazit

Alles in allem half mir Theme UI sehr, den Job schnell zu erledigen. Angefangen bei der Übergabe von Design zu Code (unter Verwendung der gleichen Design-Tokens) über die Verwendung der Breakpoint-Syntax in der GraphQL-Ebene von Gatsby bis hin zur individuellen Gestaltung von Themeneinträgen. Natürlich bietet Theme UI alles, was es auf der eigenen Website sagt: Ergonomic, Themeable, Contraint-based.. Und im Falle von Gatsby Themes: Auch Shadowable.

Ich empfehle die Verwendung von Theme UI für deine Projekte und insbesondere für Gatsby Themes 🎉

Lust auf mehr? Lies alle Beiträge in der Kategorie Coding

Weitere Beiträge