Comment nous avons abandonné l'utilisation du Styled-System pour créer des composants et inventé notre propre vélo

Bonjour à tous! Mon nom est Sasha, je suis cofondateur et développeur en chef à temps partiel chez Quarkly. Dans cet article, je veux parler de la façon dont le concept de CSS atomique, auquel nous adhérons, couplé aux lacunes de la fonctionnalité Styled-System (et Rebass, comme cas particulier d'utilisation de cette bibliothèque) nous a encouragés à créer notre propre outil, que nous avons appelé Atomize.

Un petit préambule. Notre projet Quarkly est un mélange d'un éditeur graphique (comme Figma, Sketch) et d'un concepteur de site (comme Webflow) avec l'ajout des fonctionnalités inhérentes à l'IDE classique. À propos de Quarkly, nous écrirons un article séparé, il y a quelque chose à dire et à montrer, mais aujourd'hui nous parlerons de l'Atomize mentionné ci-dessus.

Atomize est la base de tout le projet et nous permet de résoudre des problèmes qui seraient impossibles ou difficiles à résoudre en utilisant Styled-System et Rebass. Au minimum, la solution serait beaucoup moins élégante.

S'il vous reste peu de temps pour maîtriser l'intégralité du message maintenant, vous pouvez vous familiariser avec Atomize sur notre GitHub .

Et pour rendre la connaissance plus agréable, nous lançons un concours pour l'assemblage de composants React à l'aide d'Atomize. Plus à ce sujet à la fin de l'article.

Comment tout a commencé


Commençant à développer Quarkly, nous avons convenu que nous voulons donner à notre utilisateur la possibilité de composer sur des composants, mais sans avoir besoin d'utiliser un fichier CSS séparé. Pour rendre le code aussi minimaliste que possible, mais conserver toutes les fonctionnalités CSS, contrairement aux styles en ligne.

La tâche n'est pas innovante et, à première vue, est tout à fait résolue à l'aide de Styled-System et Rebass. Mais cette fonctionnalité n'était pas suffisante pour nous, et en plus nous avons rencontré les problèmes suivants:

  • travail inconfortable avec des points d'arrêt;
  • manque de capacité à écrire des styles pour le survol de l'état, la concentration, etc.;
  • Le mécanisme de travail sur des sujets ne nous a pas semblé suffisamment flexible.

Qu'est-ce qu'Atomize (brièvement)


image

Parmi les principales fonctionnalités d'Atomize, nous pouvons distinguer les suivantes:

  • la possibilité d'utiliser des variables du sujet dans les propriétés css composites;
  • prise en charge du survol et de toutes les autres pseudo-classes;
  • alias courts pour chaque propriété (comme dans emmet);
  • la possibilité de spécifier des styles pour un point d'arrêt spécifique, tout en maintenant la lisibilité du balisage;
  • interface minimaliste.

Atomize a deux objectifs principaux:

  • créer des composants qui prennent en charge le CSS et les thèmes atomiques;
  • créer des widgets pour l'édition interactive dans le projet Quarkly.

Atomiser les instructions d'utilisation


Avant de commencer le travail, il est nécessaire d'établir les dépendances:

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

Atomize est un wrapper autour du composant de style et possède une API similaire. Il suffit d'appeler la méthode avec le nom de l'élément requis:

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

En sortie, nous obtenons un composant react qui peut accepter n'importe quel CSS comme accessoire.
Pour faciliter l'utilisation, un système d'alias de propriété a été développé. Par exemple, bgc === backgroundColor

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

Une liste complète des propriétés et des alias peut être trouvée ici .

Le mécanisme d'héritage React est également fourni:

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

Travailler avec des thèmes


A ce sujet, il me semble, il faut en dire plus. Les thèmes de Quarkly sont basés sur des variables CSS. La caractéristique clé est la possibilité de réutiliser des variables à la fois des accessoires et du sujet lui-même, sans avoir besoin d'abstractions supplémentaires sous la forme de fonctions de modèle et de traitement supplémentaire ultérieur par l'utilisateur.

Pour utiliser des variables de la rubrique, il suffit de décrire la propriété dans la rubrique et de faire référence à cette propriété en utilisant le préfixe "-".

Les variables peuvent être utilisées comme dans JSX:

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

(La couleur # 04080C est disponible via la propriété --colors-dark)

Donc, dans le sujet lui-même:

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>
);

(Nous avons réutilisé la variable des couleurs, en la connectant au thème des bordures)

Pour les couleurs dans le balisage JSX, une syntaxe simplifiée est fournie:

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

Pour travailler avec des expressions multimédias, les thèmes ont un point d'arrêt.
Vous pouvez ajouter un préfixe à n'importe quelle propriété sous la forme d'un nom de clé de point d'arrêt.

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>
);

Le code source des sujets peut être trouvé ici .

Effets


La principale différence entre Atomize et Styled-System réside dans les «effets». Qu'est-ce que c'est et pourquoi est-il nécessaire?
Imaginons que vous créez un composant Button, modifiez sa couleur et sa bordure, mais comment attribuer des styles au survol, à la mise au point, etc.? Ici, les effets viennent à la rescousse.

Lors de la création d'un composant, transférez simplement l'objet avec la configuration:

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

La clé est le préfixe du nom des accessoires et la valeur est le sélecteur CSS. Ainsi, nous avons supprimé le besoin de toutes les pseudo-classes.

Maintenant, si nous spécifions le préfixe de survol d'une propriété CSS, il sera appliqué avec un certain effet. Par exemple, lorsque vous survolez:

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

Vous pouvez également combiner des effets avec des expressions multimédias:

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

Quelques exemples


Pour visualiser les informations ci-dessus, assemblons maintenant un composant intéressant. Nous avons préparé deux exemples:


Dans le deuxième exemple, nous avons utilisé la plupart des fonctionnalités, ainsi qu'une API externe.

Mais ce n'est pas tout


Le deuxième objectif d'Atomize, comme vous l'avez mentionné ci-dessus, est de créer des widgets dans Quarkly sur la base de composants de réaction personnalisés.

Pour ce faire, enveloppez simplement votre composant dans Atomize et décrivez sa configuration afin que Quarkly puisse comprendre quelles propriétés peuvent être modifiées de manière interactive:

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" }
);

Les champs de configuration du composant ressemblent à ceci:

  • effets - définit les pseudo-classes du navigateur (survol, focus, etc.);
  • description - une description du composant qui apparaîtra lorsque le curseur survolera son nom;
  • propInfo - configuration des contrôles qui seront affichés dans le panneau de droite (onglet accessoires).

Comment déterminer les accessoires qui seront affichés dans le panneau de droite (onglet accessoires):

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

Options de contrôle possibles:

  • contribution
  • sélectionner
  • Couleur
  • Police de caractère
  • ombre
  • transition
  • transformer
  • filtre,
  • Contexte
  • checkbox-icon,
  • radio-icône,
  • groupe radio
  • case à cocher.

Un autre exemple. Ici, nous avons ajouté notre composant au système et maintenant nous pouvons le modifier de manière interactive:


Merci à ceux qui ont maîtrisé le matériel jusqu'au bout! Je m'excuse d'avance pour la confusion, c'est la première expérience en écrivant de tels articles. Je serais reconnaissant pour la critique.

Et maintenant la compétition!


Afin de réchauffer légèrement l’intérêt de la communauté pour une connaissance plus approfondie d’Atomize, nous avons décidé de suivre le chemin simple et compréhensible (comme Atomize lui-même) - nous lançons un concours!

Toutes les informations sur les termes, les règles et les prix sont disponibles sur le site officiel du concours.

En bref: pour participer et gagner, vous devez trouver (ou trouver un composant prêt à l'emploi) intéressant et utile sur React et l'adapter aux exigences d'Atomize. Nous sélectionnerons et récompenserons les gagnants dans plusieurs catégories à la fois. Des prix supplémentaires de notre équipe en cas d'ajout de votre composant à Quarkly sont garantis.

All Articles