11.17.5 • Published 12 days ago

@focus4/styling v11.17.5

Weekly downloads
221
License
MIT
Repository
github
Last release
12 days ago

Module theme

Gestion du CSS

Gérer le style de composants est un problème compliqué à résoudre correctement. Bien sûr, il est totalement trivial d'écrire des classes en CSS et de les appliquer à des balises HTML, mais il faut beaucoup de bonne volonté et de rigueur pour le faire de façon propre et maintenable. Etant bien souvent victime de négligence de la part des développeurs, on se retrouve rapidement en enfer.

Il existe des tonnes de librairies et de pratiques différentes pour tenter de mettre de l'ordre dans notre CSS. La solution mise en oeuvre dans Focus V4 se base sur différentes idées piochées un peu partout :

Modules CSS

Un module CSS est un fichier CSS que l'on importe directement dans un fichier de composant. Le contenu de l'import est un object contenant les noms de toutes les classes CSS définies dans le fichier, que l'on peut utiliser directement en tant que className sur un tag HTML. L'intérêt de cet usage est que l'on peut demander à Webpack de brouiller le nom de classes à la compilation pour ainsi effectivement "scoper" le CSS aux composants qui l'ont importé. Ainsi, on obtient une isolation du CSS que l'on écrit et on peut simplifier beaucoup les noms de classes, quasiment supprimer le nesting et se forcer à regrouper les styles avec les composants qui les utilisent car ils sont liés par le code.

Il est également possible de générer automatiquement des types pour ces imports CSS (un fichier *.d.ts contenant le nom de toutes les classes globalement) avec typed-css-modules, ce qui permet de contrôler le nom des classes que l'on importe et de planter à la compilation si on se trompe/on supprime/on refactore du CSS. C'est quasiment gratuit (une commande tcm à lancer régulièrement) et c'est pratique.

Injection de classes CSS

Le scoping des classes est une fonctionnalité à double tranchant, car elle va nous empêcher de surcharger directement le CSS des composants de la librairie. Pour résoudre ce problème, on va utilise la librairie react-css-themr, fournie avec React Toolbox, qui permet de faire de la fusion de modules CSS. Avec l'aide de l'API de Context de React, on va construire un combo Provider/Consumer (ThemeProvider et themr()) autour d'une propriété theme qui contient les classes CSS à utiliser dans un composant. La fonction themr va créer un composant qui va permettre de fusionner les classes issues du style par défaut (celui du framework), celui passé dans le ThemeProvider (le vôtre) et celui passé en Props.

Par exemple, le Display est défini ainsi:

// Imports
import styles from "./__style__/display.css";
export type DisplayStyle = Partial<typeof styles>;
const Theme = themr("display", styles);

/* bla bla */

    // Render
    render() {
        /* bla bla */
        return (
            <Theme theme={this.props.theme}>
                {theme =>
                    <div data-focus="display" className={theme.display}>
                        {formatter && formatter(displayed) || displayed}
                    </div>
                }
            </Theme>
        );
    }

Le composant Theme ainsi créé prend une fonction de rendu comme children, comme le Context.Consumer qu'il pose, à laquelle le theme fusionné sera passé.

Le Layout inclus déjà le ThemeProvider, donc pour surcharger du CSS de manière globale il suffit donc d'ajouter vos propres classes dans la propriété appTheme :

import {Layout} from "focus4/layout";
import {deployed, scrolling} from "./styles.css";

ReactDOM.render(
    <Layout
        appTheme={{
            display: {
                display
            }
        }}
    >
        {/* Votre appli */}
    </Layout>
);

Dans un composant fonction, on peut désormais utiliser des hooks, donc il est possible de consommer un theme via useTheme de la façon suivante :

// Imports
import styles from "./__style__/display.css";
export type DisplayStyle = Partial<typeof styles>;

function Display(props) {
    const theme = useTheme("display", styles, props.theme);
    /* bla bla */
    return (
        <div data-focus="display" className={theme.display}>
            {(formatter && formatter(displayed)) || displayed}
        </div>
    );
}
11.17.5

12 days ago

11.17.0

23 days ago

11.16.4

2 months ago

11.16.1

2 months ago

11.16.0

3 months ago

11.15.1

3 months ago

11.15.0

3 months ago

11.14.0

4 months ago

11.13.0

4 months ago

11.12.6

4 months ago

11.12.4

5 months ago

11.12.2

6 months ago

11.12.0

6 months ago

11.10.0-rc.1

8 months ago

11.10.0-rc.0

8 months ago

11.12.0-beta.0

6 months ago

11.11.0

7 months ago

11.11.3

7 months ago

11.9.0-rc.2

8 months ago

11.9.0-rc.1

8 months ago

11.9.0-rc.0

8 months ago

11.9.0

8 months ago

11.10.2

7 months ago

11.10.1

7 months ago

11.11.0-beta.0

7 months ago

11.10.0

8 months ago

11.8.4

9 months ago

11.12.0-rc.1

6 months ago

11.11.0-rc.0

7 months ago

11.12.0-rc.0

6 months ago

11.8.2

9 months ago

11.8.1

10 months ago

11.8.0

12 months ago

11.7.5

1 year ago

11.7.6

1 year ago

11.7.3

1 year ago

11.7.4

1 year ago

11.7.0-rc.0

1 year ago

11.7.0

1 year ago

11.6.6

1 year ago

11.6.2

1 year ago

11.6.0

1 year ago

11.6.0-beta.0

1 year ago

11.5.1

2 years ago

11.5.2

2 years ago

11.5.6

1 year ago

11.4.6

2 years ago

11.5.0

2 years ago

11.4.0

2 years ago

11.4.1

2 years ago

11.4.5

2 years ago

11.3.1

2 years ago

11.3.0

2 years ago

11.2.0-alpha.0

2 years ago

11.2.0

2 years ago

11.1.3

3 years ago

11.1.1

3 years ago

10.9.2

3 years ago

11.0.0

3 years ago

11.0.0-rc.0

3 years ago

11.0.0-beta.0

3 years ago

11.0.0-beta.1

3 years ago

11.0.0-6.0

3 years ago

11.0.0-preview.6

3 years ago

11.0.0-preview.7

3 years ago

11.0.0-preview.4

3 years ago

11.0.0-preview.2

3 years ago

10.9.0

3 years ago

10.9.0-beta.1

3 years ago

10.9.0-beta.0

3 years ago

11.0.0-preview.0

3 years ago

11.0.0-preview.1

3 years ago

10.8.1

3 years ago

10.8.8

3 years ago

10.8.0-preview.1

3 years ago

10.8.0-beta.0

3 years ago

10.8.1-beta.0

3 years ago

10.8.0-preview.0

3 years ago

10.8.0-test.0

3 years ago

10.7.5

3 years ago

10.8.0-alpha.0

3 years ago

10.7.4

3 years ago

10.7.2

3 years ago

10.7.1

3 years ago

10.7.1-rc.0

3 years ago

10.7.1-rc.1

3 years ago

10.7.0-rc.0

4 years ago

10.7.0-beta.5

4 years ago

10.7.0-beta.2

4 years ago

10.7.0-beta.3

4 years ago

10.7.0-beta.0

4 years ago

10.7.0-alpha.0

4 years ago

10.6.1

4 years ago

10.6.0

4 years ago

10.6.0-rc.1

4 years ago

10.6.0-rc.0

4 years ago

10.6.0-beta.9

4 years ago

10.6.0-beta.7

4 years ago

10.6.0-beta.8

4 years ago

10.6.0-beta.6

4 years ago

10.6.0-beta.5

4 years ago

10.6.0-beta.4

4 years ago

10.6.0-beta.2

4 years ago

10.6.0-beta.0

4 years ago

10.6.0-alpha.0

4 years ago

10.5.0

4 years ago

10.5.1

4 years ago

10.5.0-beta.0

4 years ago

10.5.0-alpha.1

4 years ago

10.5.0-alpha.0

4 years ago

10.4.6

4 years ago

10.4.0

4 years ago

10.3.3

4 years ago

10.3.2

4 years ago

10.3.1

4 years ago

10.3.1-beta.6

4 years ago

10.3.0-rc.2

4 years ago

10.3.0-rc.0

4 years ago

10.3.0-alpha.0

4 years ago

10.2.0-rc.1

4 years ago

10.2.0

4 years ago

10.2.0-rc.0

4 years ago

10.1.5

4 years ago

10.1.0

5 years ago

10.0.0

5 years ago

10.0.0-rc.2

5 years ago

10.0.0-rc.1

5 years ago

10.0.0-rc.0

5 years ago

10.0.0-beta.8

5 years ago

10.0.0-beta.7

5 years ago

10.0.0-beta.6

5 years ago

10.0.0-beta.2

5 years ago

10.0.0-beta.1

5 years ago

10.0.0-alpha.3

5 years ago

10.0.0-alpha.2

5 years ago

10.0.0-alpha.1

5 years ago

10.0.0-alpha.0

5 years ago