Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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.

A brief run through a few ways of handling flexibility when it comes to patterns and components: modular architectures are hard and defined patterns need to express the right level of flexibility not to defy the point of a pattern library at all.

Marco Cedaro

January 23, 2017
Tweet

More Decks by Marco Cedaro

Other Decks in Technology

Transcript

  1. Modular architecture Classes and and modifiers and containers and overrides

    Components, 
 patterns and sh*t it’s hard to deal with
  2. 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
  3. 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?
  4. 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)
  5. //_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; } } }
  6. 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; } } }
  7. 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; } } }
  8. WHY IT DOESN’T WORK The css for the module lives

    in different files and the default style could be overridden in unexpected ways.
  9. No technique offers the same flexibility. 
 Do we need

    that flexibility? How does it play with having a pattern library? ALTERNATIVES?
  10. //_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?
  11. 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; } } }
  12. 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?
  13. 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.
  14. 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.
  15. //_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; } }
  16. 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; } }
  17. 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?
  18. WHY IT DOESN’T WORK Sometime it would drive to preemptive

    abstraction, which is, most of the time, a bad idea.
  19. WE NEVER FOUND AN ANSWER How do we re-use our

    patterns in slightly different use cases?
  20. And what can be tackled without defying the point of

    even having a pattern library? WHAT ARE WE REALLY TRING TO SOLVE?
  21. 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?
  22. //_dialog.scss .dialog { width: 100%; height: 100%; //[...] } //_game-intent.scss

    .game-intent { //[...] &__dialog { @include mappy-bp(medium) { width: 43.75rem; height: auto; } } }
  23. //_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.
  24. This practices defines responsibilities in a neat way and it

    enables for specific implementations without invalidating patterns. WHY DOES IT WORK?
  25. This is really different because the latter custom class won’t

    override the Dialog styles. <div className="custom-class"> <Dialog> <!-- [...] --> </Dialog> </div> <Dialog className="custom-class"> <!-- [...] --> </Dialog>
  26. WHY IT MIGHT NOT WORK Potentially you might need a

    wrapper HTML element that could have been avoided.
  27. Helper classes, if the base components are expecting them, could

    help avoiding repeated code. <Dialog className="space-max inner-space-min"> <!-- [...] --> </Dialog>
  28. 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?
  29. 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)
  30. //_question-content-block.scss .question-content-block { //[...] &__icon-button { //[...] .icon { width:

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

    $content-block-icon-large-size; height: $content-block-icon-large-size; } }
  32. 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; } }
  33. 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?