Wie wir auf die Verwendung des Styled-Systems zur Herstellung von Komponenten verzichteten und unser eigenes Fahrrad erfanden

Hallo alle zusammen! Mein Name ist Sasha, ich bin Mitbegründer und Teilzeit-Chefentwickler bei Quarkly. In diesem Artikel möchte ich darüber sprechen, wie das Konzept des atomaren CSS, an dem wir festhalten, zusammen mit den Mängeln der Styled-System-Funktionalität (und Rebass als Sonderfall bei der Verwendung dieser Bibliothek) uns dazu ermutigte, unser eigenes Tool zu erstellen, das wir Atomize nannten.

Eine kleine Präambel. Unser Quarkly- Projekt ist eine Mischung aus einem grafischen Editor (wie Figma, Sketch) und einem Site-Designer (wie Webflow) mit der zusätzlichen Funktionalität der klassischen IDE. Über Quarkly werden wir einen separaten Beitrag schreiben, es gibt etwas zu erzählen und was zu zeigen ist, aber heute werden wir über das oben erwähnte Atomisieren sprechen.

Atomize ist die Basis des gesamten Projekts und ermöglicht es uns, Probleme zu lösen, die mit Styled-System und Rebass unmöglich oder schwer zu lösen wären. Zumindest wäre die Lösung viel weniger elegant.

Wenn jetzt wenig Zeit bleibt, um den gesamten Beitrag zu überwältigen, können Sie sich auf unserem GitHub mit Atomize vertraut machen .

Und um die Bekanntschaft angenehmer zu gestalten, starten wir einen Wettbewerb für die Montage von Reaktionskomponenten mit Atomize. Mehr dazu am Ende des Beitrags.

Wie alles begann


Mit der Entwicklung von Quarkly haben wir uns darauf geeinigt, unseren Benutzern die Möglichkeit zu geben, Komponenten zu setzen, ohne jedoch eine separate CSS-Datei verwenden zu müssen. Um den Code so minimalistisch wie möglich zu gestalten, aber im Gegensatz zu Inline-Stilen alle CSS-Funktionen beizubehalten.

Die Aufgabe ist nicht innovativ und wird auf den ersten Blick mit Hilfe des Styled-Systems und Rebass vollständig gelöst. Diese Funktionalität hat uns jedoch nicht gereicht, und außerdem sind folgende Probleme aufgetreten:

  • unbequeme Arbeit mit Haltepunkten;
  • mangelnde Fähigkeit, Stile für den Zustand Hover, Fokus usw.;
  • Der Mechanismus der Arbeit mit Themen schien uns nicht flexibel genug.

Was ist Atomize (kurz)


Bild

Von den Hauptfunktionen von Atomize können wir Folgendes hervorheben:

  • die Fähigkeit, Variablen aus dem Thema in zusammengesetzten CSS-Eigenschaften zu verwenden;
  • Unterstützung für Hover und andere Pseudoklassen;
  • kurze Aliase für jede Eigenschaft (wie in emmet);
  • die Fähigkeit, Stile für einen bestimmten Haltepunkt anzugeben, während die Lesbarkeit des Markups erhalten bleibt;
  • minimalistische Schnittstelle.

Atomize hat zwei Hauptziele:

  • Erstellen von Komponenten, die atomares CSS und Themen unterstützen;
  • Erstellen von Widgets für die interaktive Bearbeitung im Quarkly-Projekt.

Gebrauchsanweisung zerstäuben


Vor Arbeitsbeginn müssen folgende Abhängigkeiten festgestellt werden:

npm i react react-dom styled-components @quarkly/atomize @quarkly/theme

Atomize ist ein Wrapper um die gestaltete Komponente und verfügt über eine ähnliche API. Es reicht aus, die Methode mit dem Namen des erforderlichen Elements aufzurufen:

import atomize from '@quarkly/atomize';
 
const MyBox = atomize.div();

Am Ausgang erhalten wir eine Reaktionskomponente, die jedes CSS als Requisiten akzeptieren kann.
Zur Vereinfachung der Verwendung wurde ein System von Eigenschaftsaliasnamen entwickelt. Zum Beispiel bgc === backgroundColor

ReactDOM.render(<MyBox bgc="red" />, root);

Eine vollständige Liste der Eigenschaften und Aliase finden Sie hier .

Der Reaktionsvererbungsmechanismus wird ebenfalls bereitgestellt:

const MySuperComponent = ({ className }) => {
   // some logic here
   return <div className={className} />;
};
 
const MyWrappedComponent = atomize(MySuperComponent);

Arbeite mit Themen


Darüber scheint es mir notwendig, näher darauf einzugehen. Themen in Quarkly basieren auf CSS-Variablen. Das Hauptmerkmal ist die Möglichkeit, Variablen sowohl aus den Requisiten als auch aus dem Thema selbst wiederzuverwenden, ohne dass zusätzliche Abstraktionen in Form von Vorlagenfunktionen und eine anschließende zusätzliche Verarbeitung durch den Benutzer erforderlich sind.

Um Variablen aus dem Thema zu verwenden, reicht es aus, die Eigenschaft im Thema zu beschreiben und mit dem Präfix "-" auf diese Eigenschaft zu verweisen.

Variablen können wie in JSX verwendet werden:

import Theme from "@quarkly/theme";
 
const theme = {
   colors: {
       dark: "#04080C",
   },
};
export const MyComp = () => (
   <Theme>
       <Box bgc="--colors-dark" height="100px" width="100px" />
   </Theme>
);

(Die Farbe # 04080C ist über die Eigenschaft --colors-dark verfügbar.)

Also im Motiv selbst:

import Theme from "@quarkly/theme";
 
const theme = {
   colors: {
       dark: "#04080C",
   },
   borders: {
       dark: "5px solid --colors-dark",
   },
};
export const MyComp = () => (
   <Theme>
       <Box border="--borders-dark" height="100px" width="100px" />
   </Theme>
);

(Wir haben die Variable aus den Farben wiederverwendet und sie mit dem Rahmen-Thema verbunden.)

Für Farben im JSX-Markup wird eine vereinfachte Syntax bereitgestellt:

import Theme from "@quarkly/theme";
 
const theme = {
   colors: {
       dark: "#04080C",
   },
};
export const MyComp = () => (
   <Theme>
       <Box bgc="--dark" height="100px" width="100px" />
   </Theme>
);

Für die Arbeit mit Medienausdrücken haben Themen einen Haltepunkt.
Sie können jeder Eigenschaft ein Präfix in Form eines Haltepunktschlüsselnamens hinzufügen.

import Theme from "@quarkly/theme";
 
const theme = {
   breakpoints: {
       sm: [{ type: "max-width", value: 576 }],
       md: [{ type: "max-width", value: 768 }],
       lg: [{ type: "max-width", value: 992 }],
   },
   colors: {
       dark: "#04080C",
   },
   borders: {
       dark: "5px solid --colors-dark",
   },
};
export const MyComp = () => (
   <Theme>
       <Box
           md-bgc="--dark"
           border="--borders-dark"
           height="100px"
           width="100px"
       />
   </Theme>
);

Quellcode für Themen finden Sie hier .

Auswirkungen


Der Hauptunterschied zwischen Atomize und Styled-System sind die „Effekte“. Was ist das und warum wird es benötigt?
Stellen wir uns vor, Sie erstellen eine Button-Komponente, ändern ihre Farbe und ihren Rand, aber wie weisen Sie Hover, Fokus usw. Stile zu? Hier kommen die Effekte zur Rettung.

Übertragen Sie beim Erstellen einer Komponente einfach das Objekt mit der Konfiguration:

const MySuperButton = atomize.button({
 effects: {
   hover: ":hover",
   focus: ":focus",
   active: ":active",
   disabled: ":disabled",
 },
});

Der Schlüssel ist das Präfix im Requisitennamen und der Wert ist der CSS-Selektor. Damit haben wir die Notwendigkeit für alle Pseudoklassen geschlossen.

Wenn wir nun das Hover-Präfix für eine CSS-Eigenschaft angeben, wird es mit einem bestimmten Effekt angewendet. Zum Beispiel, wenn Sie mit der Maus über Folgendes fahren:

ReactDOM.render(<MySuperButton hover-bgc="blue" />, root);

Sie können Effekte auch mit Medienausdrücken kombinieren:

ReactDOM.render(<MySuperButton md-hover-bgc="blue" />, root);

Einige Beispiele


Um die obigen Informationen zu visualisieren, stellen wir nun eine interessante Komponente zusammen. Wir haben zwei Beispiele vorbereitet:


Im zweiten Beispiel haben wir den größten Teil der Funktionalität sowie eine externe API verwendet.

Aber das ist nicht alles


Der zweite Zweck von Atomize besteht, wie oben erwähnt, darin, Widgets in Quarkly basierend auf benutzerdefinierten Reaktionskomponenten zu erstellen.

Um dies zu tun, verpacken Sie Ihre Komponente einfach in Atomize und beschreiben Sie ihre Konfiguration, damit Quarkly verstehen kann, welche Eigenschaften interaktiv bearbeitet werden können:

export default atomize(PokemonCard)(
 {
   name: "PokeCard",
   effects: {
     hover: ":hover",
   },
   description: {
     // past here description for your component
     en: "PokeCard — my awesome component",
   },
   propInfo: {
     // past here props description for your component
     name: {
       control: "input",
     },
   },
 },
 { name: "pikachu" }
);

Die Konfigurationsfelder für die Komponente sehen folgendermaßen aus:

  • Effekte - Definiert Browser-Pseudoklassen (Hover, Fokus usw.).
  • description - Eine Beschreibung der Komponente, die angezeigt wird, wenn sich der Cursor über dem Namen befindet.
  • propInfo - Konfiguration der Steuerelemente, die im rechten Bereich angezeigt werden (Registerkarte Requisiten).

So bestimmen Sie die Requisiten, die auf der rechten Seite angezeigt werden (Registerkarte Requisiten):

propInfo: {
   yourCustomProps: { //  
       description: { en: "test" }, //    
       control: "input" //  
   }
}

Mögliche Steuerungsoptionen:

  • Eingang
  • wählen
  • Farbe
  • Schriftart
  • Schatten
  • Überleitung
  • verwandeln
  • Filter,
  • Hintergrund
  • Kontrollkästchen-Symbol,
  • Radiosymbol,
  • Radiogruppe
  • Kontrollkästchen.

Noch ein Beispiel. Hier haben wir unsere Komponente zum System hinzugefügt und können sie nun interaktiv bearbeiten:


Vielen Dank an diejenigen, die das Material bis zum Ende gemeistert haben! Ich entschuldige mich im Voraus für die Verwirrung, dies ist die erste Erfahrung beim Schreiben solcher Artikel. Für die Kritik wäre ich dankbar.

Und jetzt die Konkurrenz!


Um das Interesse der Community an einer engeren Bekanntschaft mit Atomize etwas zu wecken, haben wir uns entschlossen, dem einfachen und verständlichen Weg (wie Atomize selbst) zu folgen - wir starten einen Wettbewerb!

Alle Informationen zu den Bedingungen, Regeln und Preisen sind auf der offiziellen Website des Wettbewerbs verfügbar .

Kurz gesagt: Um teilzunehmen und zu gewinnen, müssen Sie eine interessante und nützliche Komponente für React entwickeln (oder eine fertige finden) und diese an die Anforderungen von Atomize anpassen. Wir werden die Gewinner in mehreren Kategorien gleichzeitig auswählen und auszeichnen. Zusätzliche Preise von unserem Team für den Fall, dass Sie Ihre Komponente zu Quarkly hinzufügen, sind garantiert.

All Articles