Slide 1

Slide 1 text

Modular architecture

Slide 2

Slide 2 text

Modular architecture Classes and Components

Slide 3

Slide 3 text

Modular architecture Classes and Components and Modifiers

Slide 4

Slide 4 text

Modular architecture Classes and Components and modifiers and containers

Slide 5

Slide 5 text

Modular architecture Classes and Components and modifiers and containers and overrides

Slide 6

Slide 6 text

Modular architecture Classes and and modifiers and containers and overrides Components, 
 patterns and sh*t it’s hard to deal with

Slide 7

Slide 7 text

Components, 
 patterns and sh*t 
 it’s hard to deal with

Slide 8

Slide 8 text

Components, 
 patterns and sh*t 
 it’s hard to deal with or… 
 How I came up with a good use of quotes from Lost in Translation

Slide 9

Slide 9 text

The issue

Slide 10

Slide 10 text

THE ISSUE How do we manage our code, in order to re-use patterns without making them too rigid for the day to day activities?

Slide 11

Slide 11 text

REPHRASED How do we re-use our patterns in slightly different use cases?

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

1 2 3 4 FRAMING THE ISSUE It’s NOT about any specific tech stack It’s about modularity at its core It’s about modules responsibilities it’s about maintainability (among other coding practices)

Slide 14

Slide 14 text

Ideas and experiments

Slide 15

Slide 15 text

1 Different name spaces

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Slide 18

Slide 18 text

Slide 19

Slide 19 text

//_content-actions.scss .content-actions { //[...] &__button { flex: 1 0 auto; padding: rem-px-offset(1rem, -2px) 1rem; line-height: 1.5; &:hover, &:focus { background: $grey-1; } &:active { background: $grey-2; } } }

Slide 20

Slide 20 text

How would this rules interact with the base button styles? 
 (it’s actually useless, afaik) 
 What if we decided to refactor the base button? //_content-actions.scss .content-actions { //[...] &__button { flex: 1 0 auto; padding: rem-px-offset(1rem, -2px) 1rem; line-height: 1.5; &:hover, &:focus { background: $grey-1; } &:active { background: $grey-2; } } }

Slide 21

Slide 21 text

What role does this override play in the pattern library space? //_content-actions.scss .content-actions { //[...] &__button { flex: 1 0 auto; padding: rem-px-offset(1rem, -2px) 1rem; line-height: 1.5; &:hover, &:focus { background: $grey-1; } &:active { background: $grey-2; } } }

Slide 22

Slide 22 text

This is the most flexible way to extend anything. WHY DOES IT WORK?

Slide 23

Slide 23 text

WHY IT DOESN’T WORK The css for the module lives in different files and the default style could be overridden in unexpected ways.

Slide 24

Slide 24 text

WHY IT DOESN’T WORK We are creating many variants of the original patterns.

Slide 25

Slide 25 text

No technique offers the same flexibility. 
 Do we need that flexibility? How does it play with having a pattern library? ALTERNATIVES?

Slide 26

Slide 26 text

2 Ad hoc BEM-like modifiers

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

Slide 30

Slide 30 text

Slide 31

Slide 31 text

//_dialog.scss .dialog { //[...] &--game-intent { @include mappy-bp(medium) { width: 43.75rem; height: auto; } } }

Slide 32

Slide 32 text

//_dialog.scss .dialog { //[...] &--game-intent { @include mappy-bp(medium) { width: 43.75rem; height: auto; } } } The modifier lives in the same space of the dialog. 
 …but how many of these modifiers would we need?

Slide 33

Slide 33 text

How does this effect our performance?
 
 Does it effect our productivity? //_dialog.scss .dialog { //[...] &--wizard { @include mappy-bp(medium) { width: 43.75rem; height: 35rem; } } &--game-intent { @include mappy-bp(medium) { width: 43.75rem; height: auto; } } &--save-results { @include mappy-bp(medium) { width: 23.75rem; height: auto; } } }

Slide 34

Slide 34 text

This practice allows for a lot of flexibility, giving a reasonable control and keeping all the variants in the same space. WHY DOES IT WORK?

Slide 35

Slide 35 text

WHY IT DOESN’T WORK The generic component css files would start having knowledge of specific implementations. The file size might be effected by unused code.

Slide 36

Slide 36 text

WHY IT DOESN’T WORK Again: do we need this level of flexibility? How many variants do we need to take care of if we decided to edit the base component.

Slide 37

Slide 37 text

3 Pre-defined modifiers

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Slide 40

Slide 40 text

Slide 41

Slide 41 text

//_dialog.scss .dialog { //[...] &--prompt { display: block; overflow: hidden; max-width: map-get($dialog-prompt, max-width); height: auto; margin: map-get($dialog-prompt, margin); padding: 2rem 0 0; border-radius: 3px; } }

Slide 42

Slide 42 text

Even though it looks a lot like the previous one, the semantic value of the modifiers is really different. //_dialog.scss .dialog { //[...] &--prompt { display: block; overflow: hidden; max-width: map-get($dialog-prompt, max-width); height: auto; margin: map-get($dialog-prompt, margin); padding: 2rem 0 0; border-radius: 3px; } }

Slide 43

Slide 43 text

The patterns are at the center: no special cases, but pre-defined flavours of the basic components. 
 
 This make it easy to identify responsibilities and to refactor base components. WHY DOES IT WORK?

Slide 44

Slide 44 text

WHY IT DOESN’T WORK Sometime it would drive to preemptive abstraction, which is, most of the time, a bad idea.

Slide 45

Slide 45 text

It’s a great practice when we identify variants of base components. WHY DOES IT WORK?

Slide 46

Slide 46 text

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

The issue

Slide 49

Slide 49 text

WE NEVER FOUND AN ANSWER How do we re-use our patterns in slightly different use cases?

Slide 50

Slide 50 text

And what can be tackled without defying the point of even having a pattern library? WHAT ARE WE REALLY TRING TO SOLVE?

Slide 51

Slide 51 text

(Problem) => Solution* * see what I did there?

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

1 2 3 4 WHAT DO WE NEED TO CHANGE? Arrangement in parent components (margin, sizing, paddings…) Arrangement in relation to other components Theming (colours, borders…) What else?

Slide 55

Slide 55 text

1 Arrangement in parent components

Slide 56

Slide 56 text

Slide 57

Slide 57 text

Slide 58

Slide 58 text

//_dialog.scss .dialog { width: 100%; height: 100%; //[...] } //_game-intent.scss .game-intent { //[...] &__dialog { @include mappy-bp(medium) { width: 43.75rem; height: auto; } } }

Slide 59

Slide 59 text

//_dialog.scss .dialog { width: 100%; height: 100%; //[...] } //_game-intent.scss .game-intent { //[...] &__dialog { @include mappy-bp(medium) { width: 43.75rem; height: auto; } } } Every module has the right responsibility: parents define positioning in the parent space; children adapts and define themselves.

Slide 60

Slide 60 text

This practices defines responsibilities in a neat way and it enables for specific implementations without invalidating patterns. WHY DOES IT WORK?

Slide 61

Slide 61 text

This is really different because the latter custom class won’t override the Dialog styles.

Slide 62

Slide 62 text

WHY IT MIGHT NOT WORK Potentially you might need a wrapper HTML element that could have been avoided.

Slide 63

Slide 63 text

2 Arrangement in relation to other components

Slide 64

Slide 64 text

Slide 65

Slide 65 text

Slide 66

Slide 66 text

Helper classes, if the base components are expecting them, could help avoiding repeated code.

Slide 67

Slide 67 text

Besides the benefit of not having to come up with new class names, creating a set of positional helpers moves the conversation regarding component relationships back to the pattern library. WHY DOES IT WORK?

Slide 68

Slide 68 text

WHY IT MIGHT NOT WORK The positional classes might get stale if not codified properly in the pattern lib.
 
 We might end up with weird stuff. 
 (e.g: .space-maxYminX or .inner-space-noYmaxX)

Slide 69

Slide 69 text

3 Theming

Slide 70

Slide 70 text

//_question-content-block.scss .question-content-block { //[...] &__icon-button { //[...] .icon { width: $content-block-icon-large-size; height: $content-block-icon-large-size; } }

Slide 71

Slide 71 text

//_question-content-block.scss .question-content-block { //[...] &__icon-button { //[...] .icon { width: $content-block-icon-large-size; height: $content-block-icon-large-size; } }

Slide 72

Slide 72 text

//_question-content-block.scss .question-content-block { //[...] &__icon-button { //[...] @include icon-size($content-block-icon-medium-size); } } //_icon.scss @mixin icon-size($size) { .icon { width: $size; height: $size; } }

Slide 73

Slide 73 text

//_question-content-block.scss .question-content-block { //[...] &__icon-button { //[...] @include icon-size($content-block-icon-medium-size); } } //_icon.scss @mixin icon-size($size) { .icon { width: $size; height: $size; } }

Slide 74

Slide 74 text

The icon exposes an API to change some predefined properties The responsibilities order of things is maintained //_question-content-block.scss .question-content-block { //[...] &__icon-button { //[...] @include icon-size($content-bloc… } } //_icon.scss @mixin icon-size($size) { .icon { width: $size; height: $size; } }

Slide 75

Slide 75 text

Every base component can be as flexible as it defines itself to be. Developers always have control on what they expose. WHY DOES IT WORK?

Slide 76

Slide 76 text

WHY IT MIGHT NOT WORK The complexity of the sass logic might grow.

Slide 77

Slide 77 text

3 What else?

Slide 78

Slide 78 text

No content

Slide 79

Slide 79 text

No content

Slide 80

Slide 80 text

No content

Slide 81

Slide 81 text

No content