Slide 1

Slide 1 text

BUILDING THE MEDIA BLOCK IN REACTJS the API is an interface that needs to be designed https://www.flickr.com/photos/darpi/212323100/in/photolist-jLdg7-4zEiwa-nwFCR-cZVtBE-4NHtnv-7daytd-pce3y-4NH3fh-5TLS72-58aMX7-58aMVN-a3826y-gVDVKr-8DRhUB-nEdkNf-6tnApQ- fqJRqv-4NMHx7-7fUPoM-cNu2W-8etirE-o7PZA-wsB4L-7ABatu-8LyEF5-7iEjwY-3faCd1-9Gn1fF-4qYRms-JUKbE-7B97bb-69Uer5-5DQMzG-f4ZgsG-7TvUJp-5zyhEh-65naZh-nBkNs-5eCcAF-sErjv-4ePHGY-6kV1Q4- nxWYX-dpGR5-55vgqd-5scyot-5t7uJJ-nLQn5y-9Njbu-79B4aw

Slide 2

Slide 2 text

@STUBBORNELLA twitter really is the best way to reach me…

Slide 3

Slide 3 text

WHAT WILL WE COVER? ❖ What is a media block? ❖ Why use ReactJS ❖ Making a media block in ReactJS

Slide 4

Slide 4 text

WHAT IS THE MEDIA BLOCK? let’s look at an example from Facebook

Slide 5

Slide 5 text

MEDIA BLOCK EXAMPLE

Slide 6

Slide 6 text

ALL OF THESE ARE THE SAME OBJECT

Slide 7

Slide 7 text

WHAT DO WE KNOW? ! ❖ Can be nested ❖ Optional right button ❖ Must clearfix

Slide 8

Slide 8 text

WHAT DO WE KNOW? ! ❖ Allows top, middle, or bottom alignment

Slide 9

Slide 9 text

WHAT DON’T WE KNOW? ❖ Image width and decoration vary ❖ Right content is unknown ❖ Width unknown

Slide 10

Slide 10 text

A FEW LINES OF HTML...
Stubbornella
@Stubbornella 14 minutes ago

Slide 11

Slide 11 text

4 LINES OF CSS... _

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

I <3 HTML, WHY USE REACT? ❖ html consistency (modal debugging) ❖ smaller api (fewer breaking changes) ❖ don’t need to go everywhere a component was used to update the dom if it changes ❖ lightning fast dom updates when data changes ❖ not managing those updates manually ❖ simpler APIs (tabs example)

Slide 14

Slide 14 text

I CAN’T COVER EVERYTHING So do Ryan Florence’s tutorials: https://github.com/ ryanflorence/react-training/

Slide 15

Slide 15 text

https://www.flickr.com/photos/wscullin/3770015991/in/photolist-6K9jpH-4mbNmG-4Cryx-6K9jC4-9hYhWK-dexZ3L-bpV8UA-6K9jb8-2aRBU9-c2mfZu-8desRa-ntKGaS-8ZxBba-7RVQRi-7AbLTM-dMTqW3-4866mH-rjNaZL-7MP9RU- dhfQ5N-rfCB9g-nBshnQ-7Xn7f-87asnj-84R7FU-sepy36-dtEmrp-rhsh7A-hVCY8u-4m7NmB-qqiNK6-bMLUPp-qY4LbS-q1prK-5WoP4f-Ftxe-4mbHVY-jB4t16-5qgm94-5WjwED-7vS6fV-5WoP4N-biVihz-9KsFUo-9KpQVF-9KpQMz- BUILDING THE MEDIA BLOCK IN REACT APIs are an interface that needs to be designed

Slide 16

Slide 16 text

WHAT ARE THE ELEMENTS OF A REACT INTERFACE ❖ Elements ❖ Attributes ❖ Nested children ❖ Data Sounds a lot like html, right?

Slide 17

Slide 17 text

HOW DO YOU MAKE A MEDIA COMPONENT? in React Code var Media = React.createClass({ ! });

Slide 18

Slide 18 text

SO THEN, HOW WOULD YOU USE IT? It’s kind of like HTML, it’s called jsx My very first React component!

Slide 19

Slide 19 text

BUT, WE NEED TO EXPORT the Media component, so it can be used in other files module.exports = { Media: Media };

Slide 20

Slide 20 text

DESCRIBE IT WITH A RENDER FUNCTION This tells the browser what HTML to render. var Media = React.createClass({ render: function () { return (

{this.props.children}

); } }); just render a paragraph, for now tell React where to render children

Slide 21

Slide 21 text

WHAT ! ! ! IS GENERATED? https://www.flickr.com/photos/f-l-e-x/3096005116/in/photolist-5HzQsy-ah1UJ3-9WjzQW-q6xrU5-eQkJhu-oWah5L-noSbAV-9nNZaQ-5XZ3To-9gi7Rx-eMzU1y-9gb3m8-eQ8LqD-9WSkjF-9WSkhK-9zurtr-9WSk3X-eQkasL-eQ8GQ6- gi65Qe-9gbgVc-9geLWE-9gbiwR-k3TpbP-9EiwTi-bMTAYe-aYNGWB-6VTDDM-96t4ms-9s4Jas-bsjtmK-edG4Dq-rFb2Q-aZYKCH-Paes6-sd9Vtx-eg9fuW-9rYCnp-edgbX5-bmrzPv-9qA9iA-aMgUmz-s1AMwV-9zurqp-gXd9UH- iEyyC-3NaTMa-bodPpW-dLeWjL-bxHrbz

Slide 22

Slide 22 text

LET’S TRY IT! Sweet, this is gonna be rad. This text is our component’s children! ! ! ! !

This text is our component’s children!

Slide 23

Slide 23 text

LET’S TRY IT! Sweet, this is gonna be rad. This text is our component’s children! ! ! ! !

This text is our component’s children!

When React renders that component we get this html

Slide 24

Slide 24 text

LET’S TRY IT! Sweet, this is gonna be rad. This text is our component’s children! ! ! ! !

This text is our component’s children!

{this.props.children} When React renders that component we get this html

Slide 25

Slide 25 text

NOT VERY USEFUL, RIGHT? You'd never use react to render a simple paragraph because it already understands

tags, you can just use them!

Slide 26

Slide 26 text

LET’S BUILD AN ACTUAL MEDIA BLOCK Step 1: Add the left image

Slide 27

Slide 27 text

SO, WHAT DID WE TRY FIRST? https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji

Slide 28

Slide 28 text

TONS OF ATTRIBUTES What could go wrong? ;) https://www.flickr.com/photos/ilo_oli/5856288807/in/photolist-jpnSsc-bp1mTF-iC3JNn-feu2hV-feJdEw-dCsd6V-aQmwUk-qJvwYx-qKHp7N-qKJtpL-pMFnAC-9XxWkr-qKJEV1-q6hte9-qZZXHG-q6hp8d-qKHchA-qKJt8U-bp1mv2- b6LSWT-bKfSon-kxWCNt-b6LNN8-b8Vpk6-ehScwd-c5CMgq-qKJcqw-r3iaXK-pMieGe-9ZUFNi-aD4zaE-fDwLBF-9Vv1CF-kzarYi-9ovVLy-rVLApS-fDwKki-b5sxAg-fskG7P-bUUme1-bKgdD6-c5CMiW-a1wsSP-4u7U5a-dtv95k-dtvKP6- dtBtwJ-dtvrRR-dtBm2s-abcAqR

Slide 29

Slide 29 text

CREATE A SOURCE ATTRIBUTE We’ll use it in our render function to set the src of the image Media block content React props are a lot like HTML attributes

Slide 30

Slide 30 text

BUT WAIT, THE IMAGE CAN BE A LINK Sometimes…

Slide 31

Slide 31 text

SO, LET’S ADD AN HREF ATTRIBUTE Media block content Our render function will make this into a link wrapper (if it is set)

Slide 32

Slide 32 text

THE IMAGE CAN BE VERTICALLY ALIGNED

Slide 33

Slide 33 text

ADD AN ALIGNMENT ATTRIBUTE Media block content vertical alignment, could be top, middle or bottom

Slide 34

Slide 34 text

OH SHOOT, ACCESSIBILITY!

Slide 35

Slide 35 text

WE NEED AN ALT ATTRIBUTE Media block content Our render function will make this into an alt attribute on the tag

Slide 36

Slide 36 text

OH, AND PERFORMANCE!

Slide 37

Slide 37 text

WE NEED A HEIGHT AND WIDTH Media block content Explicit height and width allow the browser to do a single rendering/painting pass

Slide 38

Slide 38 text

SET THE GUTTER BETWEEN IMAGE AND CONTENT with the spacing attribute Media block content For when the 10px default spacing isn’t right, like a tiny icon with text

Slide 39

Slide 39 text

PROPERTIES OF THE MEDIA rather than its images

Slide 40

Slide 40 text

FOR EXAMPLE, IT’S RESPONSIVE via the stacksize (breakpoint) attribute Media block content stack size puts the image above the text at the breakpoint

Slide 41

Slide 41 text

THIS IS GETTING OUT OF HAND! But we forgot something, the media block can have a right image

Slide 42

Slide 42 text

ADD THE RIGHT IMAGE PROPERTIES This is out of control, we are going the wrong way! Media block content right image props

Slide 43

Slide 43 text

PROS/CONS ❖ It’s very explicit, we know what each thing does What works? ❖ We're basically recreating html in React, yuck! (we shouldn’t make a new different alt attribute! ❖ We have image properties and media properties all mixed up ❖ We have too many properties What doesn’t work?

Slide 44

Slide 44 text

SO, WHAT DID WE TRY NEXT? https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji

Slide 45

Slide 45 text

JSON ALL THE THINGS https://www.flickr.com/photos/bike/4797449644/in/photolist-8iWbD3-5HPWhF-QyKg5-eVYyjt-3meRNg-5HPW94-4HwYMz-utah8-3qvXS-aqsJtx-eyQK4T-42P9p1-7Th995-5oKgDS-5mJEJe-9bt9At-4zbwwo-8vDr8Z-7konhy- BhrJ9-5zHQ7E-bobveq-DmrMg-3qvNs-5HPW1P-qtLJmp-5ZCPcW-9QuNBj-5HUdgS-9thCcq-6FmTKV-7QgAua-6DZyzu-gkukag-apwsgp-8hWccC-4U7EX6-pfaKPb-hvM3q-asXuSH-at18RL-asXuDV-asXuC4-9ys6M7-phFVSp- dkdPkb-86toqn-dzVg-zVaLA-cDsK7N

Slide 46

Slide 46 text

OUR IMAGES AS JSON kinda weird, but it might work… var images = [ { "src": "http://placehold.it/50x50", "href": "http://www.google.com", "alignment": "middle", "alt": "profile photo", "height": "50px", "width": "50px" }, { "src": "http://placehold.it/50x50", "href": "http://www.google.com", "alignment": "middle", "alt": "profile photo", "height": "50px", "width": "50px" } ];

Slide 47

Slide 47 text

JSON IN THE MEDIA passed in as another property Media block content

Slide 48

Slide 48 text

JSON IN THE MEDIA passed in as another property Media block content {curly braces} mean it’s a JavaScript variable rather than a string

Slide 49

Slide 49 text

JSON IN THE MEDIA passed in as another property Media block content json goes into the images attribute {curly braces} mean it’s a JavaScript variable rather than a string

Slide 50

Slide 50 text

What works? What doesn’t work? PROS/CONS ❖ abstraction of passing in JSON means all the code isn't in the same place ❖ weird to have JSON in the middle of what looks like markup ❖ still reinventing html attributes of an tag ❖ cleaner separation of concerns (media takes care of media stuff, rather than the properties of its children)

Slide 51

Slide 51 text

WHAT DID WE DO NEXT? https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji

Slide 52

Slide 52 text

PARSING CHILDREN We decided to try including the images as children https://www.flickr.com/photos/i-am-mclovin/16535518502/in/photolist-rcbRyA-nshV4n-eAaqTz-bCfUFZ-jH4tBF-pctQQD-qNmfZS-eT3GMZ-bTJsji-N8LkW-iCxgoA-7JDTp2-mPGu7V-dV4m7G-igpkaV-dRobZv-mnUN9i-igoYgJ-bCzBBi- f9tdxa-oMiWTE-b6LMzz-rcTY6S-dYq12b-qUh6hV-f6oFCx-pmwC9Z-hNLucH-moYnBt-6uGwja-aRrBm4-mPGGDB-igp6YC-f8b3QR-igpkXB-igoY3C-o62zzh-iC3JNn-9217QQ-D3JPG-pcHyUy-pprMfU-igoJAg-hgRxSL-pqomg9- ahQDpD-4LkbKg-hNLcDy-igoJb8-9STs34

Slide 53

Slide 53 text

PARSING CHILDREN better, everything is normal html! But, it has a few drawbacks profile photo

My media content

profile photo

Slide 54

Slide 54 text

What works? What doesn’t work? PROS/CONS ❖ The images and body content need to be in a very particular order, it seems weird to expose that to the user ❖ Violates the "build components you can use without understanding CSS” principle ❖ Normal HTML ❖ Facebook does it this way

Slide 55

Slide 55 text

WHAT *ELSE* DOESN’T WORK? ❖ We could loop over children and reorder them, but how do we tell the difference between content images and media images? ❖ We were still discovering React, and didn't know how to loop over children yet ❖ React provides handy error messages and property validations. We would lose out on that if we made the images children ❖ Facebook's images aren't optional, so it's a different case

Slide 56

Slide 56 text

SO, WHAT DID WE TRY NEXT? https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji

Slide 57

Slide 57 text

REACT BUILT-IN COMPONENT In react, everything is a component.

Slide 58

Slide 58 text

FIRST, WE MAKE OUR IMAGES var leftImage = profile photo; ! var rightImage = profile photo;

Slide 59

Slide 59 text

NEXT, WE MAKE OUR MEDIA OBJECT this looks similar to the JSON example Media block content

Slide 60

Slide 60 text

NEXT, WE MAKE OUR MEDIA OBJECT this looks similar to the JSON example Media block content left and right images are passed into attributes

Slide 61

Slide 61 text

YOU CAN EVEN WRITE IT like this if you really want to } bodyAlignment='middle' stackSize='medium'> Media block content image component directly in the attribute property

Slide 62

Slide 62 text

What works? What doesn’t work? PROS/CONS ❖ HTML inside an attribute (in the latter example) is a bit odd, though it does have advantages. ❖ React passes default html attributes in to the resulting img tag, so we don't have to do anything special with height, width, src, aria and alt. ❖ We separate concerns and the image takes care of it's own properties ❖ No need to parse content

Slide 63

Slide 63 text

WHAT *ELSE* DOESN’T WORK? ❖ href will be passed through. So our image will have an href attribute. I like clean html, and that feels weird to me!

Slide 64

Slide 64 text

WE CONSIDERED GOING BACK TO PROPERTIES… but decided we should make our own wrapper to property or not to property?

Slide 65

Slide 65 text

SO, WHAT DID WE TRY NEXT? https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji

Slide 66

Slide 66 text

CUSTOM IMAGE COMPONENT And another component was born… https://www.flickr.com/photos/eltonharding/522073772/in/photolist-N8LkW-dLnt39-dsdYRQ-qcf3KQ-rgojpc-dsdWxA-dRxje9-iAgtmB-aaTYBU-mgGFrk-d3TMAf-opZhPw-nbi6ut-gMDt1W-adGAGZ-j8HqHK-gAt6ec-mc944B- nEMWpG-oQkVQ4-qR9xvi-gSVfC5-oUurRb-9jGTJD-nWUZza-e5NeHJ-aTYLCT-dTTRha-rp3zLC-qn7i8t-hQxDrG-9qcih5-sn5TTi-9aQfXm-nsgfeC-niFxPL-dRxjy7-9Ry7C3-p8VRa4-noA5cx-oovJdV-kLSLxL-dpgFWM-rhZ9Ri- dRxkm3-9qResk-kGDeJb-bprRNw-oCC5tt-oCX7iY

Slide 67

Slide 67 text

GOAL: OUTPUTS A SIMPLE TAG but won't pass through attributes that don't make sense like href

Slide 68

Slide 68 text

STEP 1: CREATE THE IMAGE COMPONENT var Image = React.createClass({ ! });

Slide 69

Slide 69 text

STEP 2: EXPORT THE IMAGE the same way we did the Media component module.exports = {Image};

Slide 70

Slide 70 text

STEP 3: GET ITS PROPERTIES and render an image var Image = React.createClass({ render() { var {href, src, children, className, ...other} = this.props; ! var image = ; ! return href ? {image} : image; } });

Slide 71

Slide 71 text

STEP 3: GET ITS PROPERTIES and render an image var Image = React.createClass({ render() { var {href, src, children, className, ...other} = this.props; ! var image = ; ! return href ? {image} : image; } }); get the properties we need

Slide 72

Slide 72 text

STEP 3: GET ITS PROPERTIES and render an image var Image = React.createClass({ render() { var {href, src, children, className, ...other} = this.props; ! var image = ; ! return href ? {image} : image; } }); get the properties we need build the image from our properties

Slide 73

Slide 73 text

STEP 3: GET ITS PROPERTIES and render an image var Image = React.createClass({ render() { var {href, src, children, className, ...other} = this.props; ! var image = ; ! return href ? {image} : image; } }); get the properties we need build the image from our properties if we have a link, wrap the image in an tag

Slide 74

Slide 74 text

STEP 4: MAKE IT RESPONSIVE by handling the responsive boolean var Image = React.createClass({ render() { var {responsive, href, src, children, className, ...other} = this.props; ! var image = ; return href ? {image} : image; } });

Slide 75

Slide 75 text

STEP 4: MAKE IT RESPONSIVE by handling the responsive boolean var Image = React.createClass({ render() { var {responsive, href, src, children, className, ...other} = this.props; ! var image = ; return href ? {image} : image; } }); get the responsive property

Slide 76

Slide 76 text

STEP 4: MAKE IT RESPONSIVE and setting the img-responsive class if the boolean is true var Image = React.createClass({ render() { var {responsive, href, src, children, className, ...other} = this.props; ! var classes = classnames({'img-responsive': responsive}, className); ! ! ! ! ! ! ! var image = {children}; return href ? {image} : image; } });

Slide 77

Slide 77 text

STEP 4: MAKE IT RESPONSIVE and setting the img-responsive class if the boolean is true var Image = React.createClass({ render() { var {responsive, href, src, children, className, ...other} = this.props; ! var classes = classnames({'img-responsive': responsive}, className); ! ! ! ! ! ! ! var image = {children}; return href ? {image} : image; } }); add this class if this evaluates to true

Slide 78

Slide 78 text

STEP 4: MAKE IT RESPONSIVE and setting the img-responsive class if the boolean is true var Image = React.createClass({ render() { var {responsive, href, src, children, className, ...other} = this.props; ! var classes = classnames({'img-responsive': responsive}, className); ! ! ! ! ! ! ! var image = {children}; return href ? {image} : image; } }); add this class if this evaluates to true then, put the class on the image

Slide 79

Slide 79 text

STEP 5: VALIDATE PROPERTIES var Image = React.createClass({ propTypes: { responsive: types.bool, href: types.string, src: types.string.isRequired }, ! render() { var {responsive, href, src, children, className, ...other} = this.props; var classes = classnames({'img-responsive': responsive}, className); ! var image = {children}; return href ? {image} : image; } });

Slide 80

Slide 80 text

STEP 5: VALIDATE PROPERTIES var Image = React.createClass({ propTypes: { responsive: types.bool, href: types.string, src: types.string.isRequired }, ! render() { var {responsive, href, src, children, className, ...other} = this.props; var classes = classnames({'img-responsive': responsive}, className); ! var image = {children}; return href ? {image} : image; } }); responsive has to be true or false

Slide 81

Slide 81 text

STEP 5: VALIDATE PROPERTIES var Image = React.createClass({ propTypes: { responsive: types.bool, href: types.string, src: types.string.isRequired }, ! render() { var {responsive, href, src, children, className, ...other} = this.props; var classes = classnames({'img-responsive': responsive}, className); ! var image = {children}; return href ? {image} : image; } });

Slide 82

Slide 82 text

STEP 5: VALIDATE PROPERTIES var Image = React.createClass({ propTypes: { responsive: types.bool, href: types.string, src: types.string.isRequired }, ! render() { var {responsive, href, src, children, className, ...other} = this.props; var classes = classnames({'img-responsive': responsive}, className); ! var image = {children}; return href ? {image} : image; } }); the href is a string

Slide 83

Slide 83 text

STEP 5: VALIDATE PROPERTIES var Image = React.createClass({ propTypes: { responsive: types.bool, href: types.string, src: types.string.isRequired }, ! render() { var {responsive, href, src, children, className, ...other} = this.props; var classes = classnames({'img-responsive': responsive}, className); ! var image = {children}; return href ? {image} : image; } });

Slide 84

Slide 84 text

STEP 5: VALIDATE PROPERTIES var Image = React.createClass({ propTypes: { responsive: types.bool, href: types.string, src: types.string.isRequired }, ! render() { var {responsive, href, src, children, className, ...other} = this.props; var classes = classnames({'img-responsive': responsive}, className); ! var image = {children}; return href ? {image} : image; } }); src is a string and required

Slide 85

Slide 85 text

STEP 5: VALIDATE PROPERTIES var Image = React.createClass({ propTypes: { responsive: types.bool, href: types.string, src: types.string.isRequired }, ! render() { var {responsive, href, src, children, className, ...other} = this.props; var classes = classnames({'img-responsive': responsive}, className); ! var image = {children}; return href ? {image} : image; } });

Slide 86

Slide 86 text

STEP 5: VALIDATE PROPERTIES var Image = React.createClass({ propTypes: { responsive: types.bool, href: types.string, src: types.string.isRequired }, ! render() { var {responsive, href, src, children, className, ...other} = this.props; var classes = classnames({'img-responsive': responsive}, className); ! var image = {children}; return href ? {image} : image; } });

Slide 87

Slide 87 text

OUR “AH-HA” MOMENT Users are still needing to specify too many things to get this component to work, they might as well just write html!

Slide 88

Slide 88 text

SO, WHAT DID WE DO NEXT? https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji https://www.flickr.com/photos/mstewartphotography/6195718653/in/photolist-aruFip-3Ym2sP-d5ipmU-61ivfM-2SmfSo-eMWyyv-7Tx3yN-p7xVZN-5LExX5-dG1RK2-86LsMW-6TDV5Y-9isMj1-cJuUm-4v2NE- amKvge-61TfaY-61PcSp-61nGEd-86FasK-qrz8VS-4bGoKp-77DPsN-7NeZKn-botCkn-8vpoEE-oTAKWV-5Sz1Fv-a5oF29-86Hf14-aS9vmZ-a8M5q6-a8Mh8k-7AKzoA-86HcPz-61HM17-7AFRcK-a8LXht-5c5LvE-a8LZXX-61Hb8A- fJgHuw-86LhDq-86Lmch-3jzdZ-5mYENE-8UMWoM-bx1iUr-p9jsSa-a865Ji

Slide 89

Slide 89 text

ELEMENTS FTW we can simplify our interface further https://www.flickr.com/photos/rejik/14681743931/in/photolist-onnLY4-nPYfhm-ed6PWM-bvWmjA-mMGE1V-j88ToM-ngTbpk-nUg38a-9n1hgv-4KZr2Z-nucMef-dd5exw-9eyaqy-8QWK1i-eaTuFL-4RbvFX-7kiwo3-7NqP2a-4R1KYB- mZEx1J-5iV12q-39v9f8-bqt2rx-7zvWs-9eyamJ-7JKZAh-hiwiDa-poG8fx-ehZRGj-684GeT-pPeQGL-efRP9f-icXKJY-aNxWqT-9niyKk-ouarpw-bmC5SK-7s5DNV-bqt3F8-bqsZ24-mZCLWp-86YqXk-e6ERub-bqtEL8-8K3pJf- kik4tg-8yYivi-8fi3Ep-dVohpu-fzmggH https://www.flickr.com/photos/rejik/14681743931/in/photolist-onnLY4-nPYfhm-ed6PWM-bvWmjA-mMGE1V-j88ToM-ngTbpk-nUg38a-9n1hgv-4KZr2Z-nucMef-dd5exw-9eyaqy-8QWK1i-eaTuFL-4RbvFX-7kiwo3-7NqP2a-4R1KYB- mZEx1J-5iV12q-39v9f8-bqt2rx-7zvWs-9eyamJ-7JKZAh-hiwiDa-poG8fx-ehZRGj-684GeT-pPeQGL-efRP9f-icXKJY-aNxWqT-9niyKk-ouarpw-bmC5SK-7s5DNV-bqt3F8-bqsZ24-mZCLWp-86YqXk-e6ERub-bqtEL8-8K3pJf- kik4tg-8yYivi-8fi3Ep-dVohpu-fzmggH

Slide 90

Slide 90 text

DESIGNERS ONLY USE 2 KINDS OF ALIGNMENT ❖ Traditional media with everything top aligned ! ! ! ❖ “Flag” component a la Harry Roberts middle aligns

Slide 91

Slide 91 text

WE MADE THESE TWO USE CASES DEAD SIMPLE ❖ We changed the media component to default to top alignment if nothing else was specified. ❖ We created the component refresh

Slide 92

Slide 92 text

What works? What doesn’t work? PROS/CONS ❖ engineers don't always know what the flag object is, documentation and teaching help ❖ with Flag and Media, we no longer need to specify alignment unless we want something weird

Slide 93

Slide 93 text

ARE ANY OF THESE WRONG? No, absolutely not. https://gist.github.com/stubbornella/e97662e4a197eb9a534a

Slide 94

Slide 94 text

CHARTS loop over children https://www.flickr.com/photos/sidereal/3326112973/in/photolist-AKC4i-9YVVYN-6EiwN6-GadYk-a67Nur-5VXHT1-Fv7K6-aozvYE-6fp6gc-6FzLjQ-fKvtt-2JGK9-bqeuyX-3jcvLj-Ljyy3-6kUXKM- bVyHMC-4dDwYk-5CGecv-6DUvgk-64Vcvp-8cK4x4-6b5yLD-jDwYG-wnfrN-vdeo8-8343Sa-dRCSgx-83wSzz-5xtVxe-5xyrZd-5VDSw6- fXTYR-82Dnu2-5VDSwa-7MNruk-81biBH-5e3irn-5e3i4T-6mxH7A-5m93Dg-5pi6WC-5uvUeA-6n89sp-c465FQ-6SDa5S-5AbJnS-cN17Zf-KGVTi-7yvvmH

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

var sortableCols = [ { name: 'name', title: 'Name', sortable: true }, { name: 'instances', title: 'Instances', sortable: true, align: 'center' }, { name: 'cpu', title: 'CPU', sortable: true, align: 'right' }, { name: 'synergy', title: 'Synergy', align: 'left' } ]

Slide 97

Slide 97 text

TABS IN BOOTSTRAP
! !
...
...
!

Slide 98

Slide 98 text

TABS IN REACT ... ...

Slide 99

Slide 99 text

https://www.flickr.com/photos/wscullin/3770015991/in/photolist-6K9jpH-4mbNmG-4Cryx-6K9jC4-9hYhWK-dexZ3L-bpV8UA-6K9jb8-2aRBU9-c2mfZu-8desRa-ntKGaS-8ZxBba-7RVQRi-7AbLTM-dMTqW3-4866mH-rjNaZL-7MP9RU- dhfQ5N-rfCB9g-nBshnQ-7Xn7f-87asnj-84R7FU-sepy36-dtEmrp-rhsh7A-hVCY8u-4m7NmB-qqiNK6-bMLUPp-qY4LbS-q1prK-5WoP4f-Ftxe-4mbHVY-jB4t16-5qgm94-5WjwED-7vS6fV-5WoP4N-biVihz-9KsFUo-9KpQVF-9KpQMz- IT’S A DESIGN DECISION each component is different

Slide 100

Slide 100 text

KEEP LOOPING BACK change the interface until it works well

Slide 101

Slide 101 text

GOOD DESIGN PRINCIPLES ❖ Many drawers - Tom O ❖ Set good defaults ❖ User shouldn’t need to understand CSS to use it ❖ Make tiny components with one job (same as CSS) ❖ Allow flexibility ❖ Prefer a complex implementation over a complex interface what has worked for us

Slide 102

Slide 102 text

WHO ARE YOUR USERS? component creators and maintainers, contributors, developers building features, actual product users https://www.flickr.com/photos/fabiansociety/16300828766/in/photolist-qQs1tQ-qAa8pJ-pVJmYw-qxNcH4-qAaDuJ-qSHJsr-5SDe5H-josG7R-dxrFDm-e6S4TN-fddCLi-po7JuN-d21PZN-ax7LAK-qBLEie-dEMphp-byfU17-nPjAPc-eZ7ooX- ctHbf5-g5QFS-naVVhZ-cFgo6s-akEb2Q-qUQi3c-aGJ83i-627cGv-aRFFNx-nSyXpr-dyXFU7-aupkvk-buYgB2-nj7Xyv-jHSXR5-9eAqzK-eNqYdm-a4GaUk-qiFrdF-dy1QsG-bPqzrk-9dEUm7-n7cmgE-gJNeKz-nigszh-mi4QjT-s76Yxa-

Slide 103

Slide 103 text

USE ALL THE TOOLS IN YOUR TOOLBOX ❖ Elements (built in and custom) ❖ Attributes (simple and objects) ❖ JSON ❖ Children

Slide 104

Slide 104 text

No content

Slide 105

Slide 105 text

styleguide.pivotal.io

Slide 106

Slide 106 text

WE OPEN SOURCED EVERYTHING Please do give us feedback npm: https://www.npmjs.com/search?q=pui github: github.com/pivotal-cf/pivotal-ui

Slide 107

Slide 107 text

THANK YOU! @stubbornella