
Hallo allerseits, mein Name ist Vitalik, ich bin ein leitender Front-End-Entwickler bei Skyeng. Unser Team erstellt eine Online-Vimbox-Plattform zum Englischlernen. Vor ungefähr einem Jahr haben der Designer und ich ein kleines UI-Kit fertiggestellt, das das Chaos in der Benutzeroberfläche und der Codebasis beseitigt hat.
Es stellte sich heraus, dass wir nicht die einzigen im Unternehmen waren, die das UI-Kit wollten, und andere Teams kamen zu uns, um Ratschläge zu erhalten, wie Sie Ihre eigenen schreiben können. Wir haben es geschafft, sie von diesem Unternehmen abzubringen und versprochen, unser eigenes zu mildern - dies hat dem Unternehmen Hunderte von Stunden Entwicklungszeit erspart. Bei der Auswahl einer Lösung haben wir uns Angular Material, benutzerdefinierte Baugruppen und CSS-Variablen angesehen und uns schließlich für letztere entschieden, trotz ihrer schwachen Kompatibilität mit SCSS, der Grundlage des vorhandenen UI-Kits. Unter dem Schnitt - Details von dem, was wir getan haben.

Das Problem
Das erste UI-Kit bestand aus Schriftarten, einer Palette, einer Reihe von Elementen zum Erstellen von Formularen (Eingabe, Schaltfläche usw.) und einem System zum Verwalten von SVG-Symbolen. Popup und Tooltip basierend auf Angular-Materialien wurden ebenfalls implementiert. Es wurde eingesperrt, weil es nur mit der "klassischen" Vimbox gearbeitet hatte : Viele Dinge wurden absichtlich eng zusammengenäht und erlaubten keine Änderungen von außen. Und Skyeng begann, neue Produkte auf derselben Plattform zu haben, zum Beispiel für Kinder.
Die Entwickler neuer Richtungen, die wussten, dass wir etwas haben, kamen um Rat. Zu unserer Überraschung kamen sie außerdem bereits mit den Layouts ihrer UI-Kits: Sie wollten ihre Lösungen von Grund auf neu entwickeln, weil Sie brauchten ein anderes Aussehen für die Komponenten. Es war klar, dass etwas schief lief, und wir schlugen vor, unsere Bibliothek zu verfeinern und die Möglichkeit ihrer Thematisierung hinzuzufügen.
Das Argument war einfach: Das Entwerfen unseres UI-Kits dauerte 200 Stunden UX-Design und mehr als 500 Stunden Entwicklungszeit. Dies ist die Zeit, die erforderlich ist, um ein System aus Schriftarten, Farben und etwa 10 Grundkomponenten zu erstellen. Wenn Sie für jedes Produkt eine separate Bibliothek schreiben, verbringt das Unternehmen dementsprechend N * 500 Stunden Entwicklungszeit. Wir dachten, dass die Verbesserung unseres UI-Kits billiger wäre und dieser Schritt nicht für jedes Produkt wiederholt werden müsste.
Unsere Argumente wurden akzeptiert, verwandte Bereiche waren bereit zu warten, und wir machten uns auf die Suche nach einer technischen Lösung.
Ausgangsdaten
Unsere Werkzeuge: Angular, SCSS.
Wir unterstützen nur moderne Browser und mit einigen Einschränkungen IE11. Das macht das Leben leichter.
Alle unsere UI-Kit-Komponenten waren mit gängigen Stilen versehen, die wir in UI kit.var.scss
als SCSS-Konstanten gestapelt haben:
@mixin fontSizeXl { @include fontSize(18px, 26px); } $colorSkillListening: #9679e0; $colorSkillListeningText: #7754d1; $colorSkillListeningBackground: mix($colorSkillListening, #ffffff, 16%); $colorSkillListeningBackgroundHover: mix($colorSkillListening, #ffffff, 8%);
Herausforderung
- Alle neuen Produkte werden aus vorhandenen Elementen zusammengesetzt, die in der "erwachsenen" Vimbox vorhanden sind - Klassenzimmer, persönliche Konten usw.
- Designer sollten große Freiheit haben, kreative Ideen, Besonderheiten und spezifische Anforderungen an neue Produkte umzusetzen.
- Gleichzeitig bleibt die Kontinuität bestehen, d.h. Unabhängig davon, wie saure Farben und verrückte Schriftarten der Designer erfindet, bleibt die Zugehörigkeit des Ergebnisses seiner Arbeit zum Skyeng-Ökosystem offensichtlich.
- All dies wird dem vorhandenen UI-Kit hinzugefügt, wobei alle Vorteile erhalten bleiben.
Lass uns gehen!
Das Ergebnis wird also gestern von uns erwartet. Wir müssen schnell technische Überprüfungen durchführen und Optionen besprechen. Bei den ersten Treffen haben wir einen Kreis möglicher Lösungen identifiziert:
Winkelmaterial
Wir schreiben nicht gerne Fahrräder, deshalb haben wir uns zuerst Angular Material zugewandt. In Komponenten werden dynamische Stile in eine separate Datei {component}-theme.scss
. Diese Stile sind an den globalen Selektor der Komponente gebunden.
CSS-Variablen
Wir haben einen guten Grund, trendige CSS-Variablen auszuprobieren. Es ist geplant, die benutzerdefinierten Teile des UI-Kits in CSS-Variablen zu transplantieren. Die Komponenten verwenden dieselben SCSS-Konstanten, aber anstelle bestimmter Werte werden CSS-Variablen in sie geschrieben.
Benutzerdefinierte Builds
Wir lieben einfache Lösungen. Warum nicht versuchen, die Baugruppe zu wechseln? Jedes Team erstellt eine eigene Datei mit Themeneinstellungen. Beim Zusammenstellen für alle benutzerdefinierten Designs werden separate Bundles mit einem eigenen Design erstellt.
Lösung
Eine Woche lang haben wir jede Option untersucht, diskutiert, die Entscheidung verschoben und erneut untersucht.
Wir lieben neue Technologien und überwachen sie, implementieren sie aber nur, wenn sie uns echte Boni geben. Wir wussten von CSS-Variablen, wir wollten sie ausprobieren, aber das Fehlen von SCSS-Funktionen verursachte viel Traurigkeit. Trotzdem waren die Vorteile dieser Option offensichtlich. Wir haben uns entschlossen herauszufinden, wie und welche SCSS-Funktionen wir verwenden und ob es möglich ist, sich mit CSS-Variablen anzufreunden.
Grundlegendes zu CSS und SCSS
Nachdem wir experimentiert hatten, stellten wir fest, dass das Hauptproblem die mangelnde Unterstützung von #hex in CSS ist: In SCSS schreiben wir rgba(#ffffff, 0.4)
, und in CSS erfordert dasselbe einen anderen Parametersatz - rgba(255, 255, 255, 0.4)
. Mit #hex funktioniert alles für uns, und wir wollen das wirklich, wirklich nicht ändern. Wir haben Lösungen gefunden, werde ich in der Reihenfolge der Zulassung sagen.
Aufhellen und abdunkeln
Unser Designer hat eine Palette entwickelt, die aus einer kleinen Anzahl von Grundfarben besteht und sich aufgrund der SCSS-Funktionen zum lighten
und darken
:
Wir haben versucht, ein Analogon für lighten
und darken
in CSS zu finden, aber nichts gefunden. Wir haben einige Tage nachgedacht, bis uns klar wurde, dass wir diese Funktionen für die Anpassung in der Bibliothek entfernen und herausnehmen müssen. Schließlich möchte jedes Team möglicherweise eine eigene Formel zum Ändern der Farbe beim Ändern des Fokus entwickeln. Beispielsweise benötigen Kollegen von Kids mehr Kontrast.
Die einfache Lösung bestand darin, unsere Transformationen auf die Seite der Plattform zu übertragen, die das Thema initialisiert. Und für die Plattform schreiben wir eine Funktion, die automatisch die notwendigen Werte erstellt:
@function getMainColors($color, $colorText) { $colors: ( text: $colorText, base: $color, background: mix($color, #ffffff, 16%), backgroundHover: mix($color, #ffffff, 8%), lightenLess: lighten($color, 5), darkenLess: darken($color, 5), lightenMore: lighten($color, 20), ); @return $colors; }
Die Plattform verwendet es beim Initialisieren von Farben:
RGBA
In unserem UI-Kit verwenden wir die Funktion rgba
. Damit passen wir die Transparenz der Grundfarben an. Wenn rgba jedoch mit #hex in SCSS funktioniert, kann CSS dies nicht. Ich musste eine Funktion schreiben, die den # hex-Wert in r / g / b zerlegt:
Da wir keine RGB-Werte mit Handles für die gesamte Palette generieren möchten, erstellen wir eine separate Funktion, die dies für jede Farbe in der Sammlung rekursiv ausführt:
Infolgedessen sieht die Initialisierung der Palette mit den generierten RGB-Werten folgendermaßen aus:
$colorValues: withRgbValues( ( text: ( base: #242d34, secondary: #50575c, label: #73797d, placeholder: #969b9e, inversed: #ffffff, inversedSecondary: #dadada, ), brand: getMainColors(#5d9cec, #4287df), positive: getMainColors(#8cc152, #55a900), accent: getMainColors(#ff3d6f, #ff255d), wrong: getMainColors(#ff6666, #fe4f44),
Die Ausgabe ist eine SCSS-Farbkarte, die dann in eine Methode umgewandelt werden kann, die sie in CSS-Variablen umwandelt. Um den Wert aus dem RGB-Thema zu erhalten, haben wir eine Funktion geschrieben:
@function getUiKitRgbVar($path...) { $path: set-nth($path, -1, #{nth($path, -1)}Rgb);
Verwandeln Sie SCSS const in CSS vars
Der erste Schritt besteht darin, eine Spiegelstruktur (ähnlich wie SCSS) zu erstellen, in der die Namen der CSS-Variablen gespeichert werden:
$colorCssVars: withRgbCssVars( ( text: ( base: getColorCssVar(text, base), secondary: getColorCssVar(text, secondary), label: getColorCssVar(text, label), placeholder: getColorCssVar(text, placeholder), inversed: getColorCssVar(text, inversed),
getColorCssVar
- eine Methode, die Variablennamen Präfixe hinzufügt. Fügen Sie das Präfix --sky
, um Kollisionen mit externen Bibliotheken zu vermeiden. --sky
Präfix - UI kit
Bibliothek zu --sky
, um Konflikte mit internen Bibliotheken zu vermeiden. Es stellte sich heraus --sky- UI kit
:
@function getColorCssVar($parts...) { @return getUiKitCssVar(color, $parts...); } @function getUiKitCssVar($parts...) { $uiKitCssVarPrefix: '--sky- UI kit'; $cssVar: $uiKitCssVarPrefix; @each $part in $parts { $cssVar: $cssVar + '-' + $part; } @return $cssVar; }
Für getColorCssVar(text, base)
wir beispielsweise --sky- UI kit-color-text-base
für die Ausgabe.
Der letzte Schliff ist ein rekursives Mixin, das Werte aus der SCSS-Struktur in Variablen mit Namen aus der CSS-Var-Struktur initialisiert:
Ein Beispiel für die Verwendung eines Themas auf der Plattform:
.popup { font-family: getUiKitVar(font, family); background-color: getUiKitVar(color, background, base); ... }
Was ist das Ergebnis?
Wir konnten CSS-Variablen verwenden und gleichzeitig die SCSS-Funktionen verwenden. Erstellt die Möglichkeit, das Erscheinungsbild der Komponenten anzupassen. Wir haben einige rekursive Methoden geschrieben, um die Erweiterung des Themas zu automatisieren. Gut und vor allem - 30 Stunden Entwicklungszeit statt N * 500.
Gewinn!