Building the Media Block in ReactJS

107
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

Transcript of Building the Media Block in ReactJS

Page 1: Building the Media Block in ReactJS

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

Page 2: Building the Media Block in ReactJS

@STUBBORNELLAtwitter really is the best way to reach me…

Page 3: Building the Media Block in ReactJS

WHAT WILL WE COVER?

❖ What is a media block? ❖ Why use ReactJS ❖ Making a media block in ReactJS

Page 4: Building the Media Block in ReactJS

WHAT IS THE MEDIA BLOCK?

let’s look at an example from Facebook

Page 5: Building the Media Block in ReactJS

MEDIA BLOCK EXAMPLE

Page 6: Building the Media Block in ReactJS

ALL OF THESE ARE THE SAME OBJECT

Page 7: Building the Media Block in ReactJS

WHAT DO WE KNOW?

!❖ Can be nested ❖ Optional right button ❖ Must clearfix

Page 8: Building the Media Block in ReactJS

WHAT DO WE KNOW?

!❖ Allows top, middle, or

bottom alignment

Page 9: Building the Media Block in ReactJS

WHAT DON’T WE KNOW?

❖ Image width and decoration vary ❖ Right content is unknown ❖ Width unknown

Page 10: Building the Media Block in ReactJS

A FEW LINES OF HTML...

<div class="media attribution"> <a href="http://twitter.com/stubbornella" class="img"> <img src="mini.jpg" alt="Stubbornella" /> </a> <div class="bd">@Stubbornella 14 minutes ago</div></div>

Page 11: Building the Media Block in ReactJS

4 LINES OF CSS...

_

Page 12: Building the Media Block in ReactJS
Page 13: Building the Media Block in ReactJS

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)

Page 14: Building the Media Block in ReactJS

I CAN’T COVER

EVERYTHINGSo do Ryan Florence’s

tutorials: https://github.com/

ryanflorence/react-training/

Page 15: Building the Media Block in ReactJS

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-

r5vEd9-nkFqB2-4mbL7L-7VBztH

BUILDING THE MEDIA BLOCK IN REACT

APIs are an interface that needs to be designed

Page 16: Building the Media Block in ReactJS

WHAT ARE THE ELEMENTS OF A REACT INTERFACE

❖ Elements ❖ Attributes ❖ Nested children ❖ Data

Sounds a lot like html, right?

Page 17: Building the Media Block in ReactJS

HOW DO YOU MAKE A MEDIA COMPONENT?

in React

Codevar Media = React.createClass({ !});

Page 18: Building the Media Block in ReactJS

SO THEN, HOW WOULD YOU USE IT?

It’s kind of like HTML, it’s called jsx

<Media> My very first React component! </Media>

Page 19: Building the Media Block in ReactJS

BUT, WE NEED TO EXPORTthe Media component, so it can be used in other files

module.exports = { Media: Media };

Page 20: Building the Media Block in ReactJS

DESCRIBE IT WITH A RENDER FUNCTIONThis tells the browser what HTML to render.

var Media = React.createClass({ render: function () { return ( <p> {this.props.children} </p> ); } });

just render a paragraph, for now

tell React where to render children

Page 21: Building the Media Block in ReactJS

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

Page 22: Building the Media Block in ReactJS

LET’S TRY IT!Sweet, this is gonna be rad.

<Media> This text is our component’s children! </Media> !!!!<p> This text is our component’s children! </p>

Page 23: Building the Media Block in ReactJS

LET’S TRY IT!Sweet, this is gonna be rad.

<Media> This text is our component’s children! </Media> !!!!<p> This text is our component’s children! </p>

When React renders that component we get this html

Page 24: Building the Media Block in ReactJS

LET’S TRY IT!Sweet, this is gonna be rad.

<Media> This text is our component’s children! </Media> !!!!<p> This text is our component’s children! </p>

{this.props.children}

When React renders that component we get this html

Page 25: Building the Media Block in ReactJS

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

already understands <p> tags, you can just use them!

Page 26: Building the Media Block in ReactJS

LET’S BUILD AN ACTUAL MEDIA BLOCK

Step 1: Add the left image

Page 27: Building the Media Block in ReactJS

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

Page 28: Building the Media Block in ReactJS

TONS OF ATTRIBUTESWhat 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

Page 29: Building the Media Block in ReactJS

CREATE A SOURCE ATTRIBUTE

We’ll use it in our render function to set the src of the image

<Media leftImageSource='http://placehold.it/50x50'> Media block content </Media>

React props are a lot like HTML

attributes

Page 30: Building the Media Block in ReactJS

BUT WAIT, THE IMAGE CAN BE A LINK

Sometimes…

Page 31: Building the Media Block in ReactJS

SO, LET’S ADD AN HREF ATTRIBUTE

<Media leftImageSource='http://placehold.it/50x50' leftImageHref='http://www.google.com'> Media block content </Media>

Our render function will make this into a link wrapper (if it is set)

Page 32: Building the Media Block in ReactJS

THE IMAGE CAN BE VERTICALLY ALIGNED

Page 33: Building the Media Block in ReactJS

ADD AN ALIGNMENT ATTRIBUTE

<Media leftImageSource='http://placehold.it/50x50' leftImageHref='http://www.google.com' leftImageAlignment='middle'> Media block content </Media>

vertical alignment, could be top, middle or bottom

Page 34: Building the Media Block in ReactJS

OH SHOOT, ACCESSIBILITY!

Page 35: Building the Media Block in ReactJS

WE NEED AN ALT ATTRIBUTE

<Media leftImageSource='http://placehold.it/50x50' leftImageHref='http://www.google.com' leftImageAlignment='middle' leftImageAlt="profile photo"> Media block content </Media>

Our render function will make this into an alt attribute on the

<img> tag

Page 36: Building the Media Block in ReactJS

OH, AND PERFORMANCE!

Page 37: Building the Media Block in ReactJS

WE NEED A HEIGHT AND WIDTH

<Media leftImageSource='http://placehold.it/50x50' leftImageHref='http://www.google.com' leftImageAlignment='middle' leftImageAlt="profile photo" leftImageHeight="50px" leftImageWidth="50px"> Media block content </Media>

Explicit height and width allow the browser to do a single rendering/painting

pass

Page 38: Building the Media Block in ReactJS

SET THE GUTTER BETWEEN IMAGE AND CONTENT

with the spacing attribute

<Media leftImageSource='http://placehold.it/50x50' leftImageHref='http://www.google.com' leftImageAlignment='middle' leftImageAlt="profile photo" leftImageHeight="50px" leftImageWidth="50px" leftImageSpacing="medium"> Media block content </Media>

For when the 10px default spacing isn’t right, like a tiny

icon with text

Page 39: Building the Media Block in ReactJS

PROPERTIES OF THE MEDIArather than its images

Page 40: Building the Media Block in ReactJS

FOR EXAMPLE, IT’S RESPONSIVE

via the stacksize (breakpoint) attribute

<Media leftImageSource='http://placehold.it/50x50' leftImageHref='http://www.google.com' leftImageAlignment='middle' leftImageAlt="profile photo" leftImageHeight="50px" leftImageWidth="50px" leftImageSpacing="medium" stackSize='medium'> Media block content </Media>

stack size puts the image above the text at the

breakpoint

Page 41: Building the Media Block in ReactJS

THIS IS GETTING OUT OF HAND!

But we forgot something, the media block can have a right image

Page 42: Building the Media Block in ReactJS

ADD THE RIGHT IMAGE PROPERTIES

This is out of control, we are going the wrong way!

<Media leftImageSource='http://placehold.it/50x50' leftImageHref='http://www.google.com' leftImageAlignment='middle' leftImageAlt="profile photo" leftImageHeight="50px" leftImageWidth="50px" rightImageSource='http://placehold.it/50x50' rightImageHref='http://www.google.com' rightImageAlignment='middle' rightImageAlt="profile photo" rightImageHeight="50px" rightImageWidth="50px" rightImageSpacing="medium" bodyAlignment='middle' stackSize='medium'> Media block content </Media>

right image props

Page 43: Building the Media Block in ReactJS

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?

Page 44: Building the Media Block in ReactJS

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

Page 45: Building the Media Block in ReactJS

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

Page 46: Building the Media Block in ReactJS

OUR IMAGES AS JSONkinda 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" } ];

Page 47: Building the Media Block in ReactJS

JSON IN THE MEDIApassed in as another property

<Media images={images} bodyAlignment='middle' stackSize='medium'> Media block content </Media>

Page 48: Building the Media Block in ReactJS

JSON IN THE MEDIApassed in as another property

<Media images={images} bodyAlignment='middle' stackSize='medium'> Media block content </Media>

{curly braces} mean it’s a JavaScript variable rather than a string

Page 49: Building the Media Block in ReactJS

JSON IN THE MEDIApassed in as another property

<Media images={images} bodyAlignment='middle' stackSize='medium'> Media block content </Media>

json goes into the images attribute

{curly braces} mean it’s a JavaScript variable rather than a string

Page 50: Building the Media Block in ReactJS

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 <img> tag

❖ cleaner separation of concerns (media takes care of media stuff, rather than the properties of its children)

Page 51: Building the Media Block in ReactJS

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

Page 52: Building the Media Block in ReactJS

PARSING CHILDRENWe 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

Page 53: Building the Media Block in ReactJS

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

<Media> <img src='http://placehold.it/50x50' href='http://www.google.com' alignment='middle' alt="profile photo" height="50px" width="50px" > <p>My media content</p> <img src='http://placehold.it/50x50' href='http://www.google.com' alignment='middle' alt="profile photo" height="50px" width="50px" > </Media>

Page 54: Building the Media Block in ReactJS

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

Page 55: Building the Media Block in ReactJS

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

Page 56: Building the Media Block in ReactJS

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

Page 57: Building the Media Block in ReactJS

REACT BUILT-IN <IMG> COMPONENT

In react, everything is a component.

Page 58: Building the Media Block in ReactJS

FIRST, WE MAKE OUR IMAGES

var leftImage = <img src='http://placehold.it/50x50' href='http://www.google.com' alignment='middle' alt="profile photo" height="50px" width="50px">; !var rightImage = <img src='http://placehold.it/50x50' href='http://www.google.com' alignment='middle' alt="profile photo" height="50px" width=“50px">;

Page 59: Building the Media Block in ReactJS

NEXT, WE MAKE OUR MEDIA OBJECT

this looks similar to the JSON example

<Media leftImage={leftImage} rightImage={rightImage} bodyAlignment='middle' stackSize='medium'> Media block content </Media>

Page 60: Building the Media Block in ReactJS

NEXT, WE MAKE OUR MEDIA OBJECT

this looks similar to the JSON example

<Media leftImage={leftImage} rightImage={rightImage} bodyAlignment='middle' stackSize='medium'> Media block content </Media>

left and right images are passed into attributes

Page 61: Building the Media Block in ReactJS

YOU CAN EVEN WRITE ITlike this if you really want to

<Media leftImage={<img src='http://placehold.it/50x50' href='http://www.google.com' alignment='middle' alt="profile photo" height="50px" width="50px">} bodyAlignment='middle' stackSize='medium'> Media block content </Media>

image component directly in the attribute property

Page 62: Building the Media Block in ReactJS

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

Page 63: Building the Media Block in ReactJS

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!

<div class="media"> <a href="styleguide.pivotal.io"> <img href="styleguide.pivotal.io" /> ...

Yuck!

Page 64: Building the Media Block in ReactJS

WE CONSIDERED GOING BACK TO PROPERTIES…

but decided we should make our own <img> wrapper

<Media leftImageHref="styleguide.pivotal.io">

to property or not to property?

Page 65: Building the Media Block in ReactJS

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

Page 66: Building the Media Block in ReactJS

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

Page 67: Building the Media Block in ReactJS

GOAL: OUTPUTS A SIMPLE <IMG> TAG

but won't pass through attributes that don't make sense like href

Page 68: Building the Media Block in ReactJS

STEP 1: CREATE THE IMAGE COMPONENT

var Image = React.createClass({ !});

Page 69: Building the Media Block in ReactJS

STEP 2: EXPORT THE IMAGEthe same way we did the Media component

module.exports = {Image};

Page 70: Building the Media Block in ReactJS

STEP 3: GET ITS PROPERTIESand render an image

var Image = React.createClass({ render() { var {href, src, children, className, ...other} = this.props; ! var image = <img {...other} src={src} className={classes}>; ! return href ? <a {...{href}}>{image}</a> : image; } });

Page 71: Building the Media Block in ReactJS

STEP 3: GET ITS PROPERTIESand render an image

var Image = React.createClass({ render() { var {href, src, children, className, ...other} = this.props; ! var image = <img {...other} src={src} className={classes}>; ! return href ? <a {...{href}}>{image}</a> : image; } });

get the properties we need

Page 72: Building the Media Block in ReactJS

STEP 3: GET ITS PROPERTIESand render an image

var Image = React.createClass({ render() { var {href, src, children, className, ...other} = this.props; ! var image = <img {...other} src={src} className={classes}>; ! return href ? <a {...{href}}>{image}</a> : image; } });

get the properties we need

build the image from our properties

Page 73: Building the Media Block in ReactJS

STEP 3: GET ITS PROPERTIESand render an image

var Image = React.createClass({ render() { var {href, src, children, className, ...other} = this.props; ! var image = <img {...other} src={src} className={classes}>; ! return href ? <a {...{href}}>{image}</a> : image; } });

get the properties we need

build the image from our properties

if we have a link, wrap the image in an <a> tag

Page 74: Building the Media Block in ReactJS

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 = <img {...other} src={src}>; return href ? <a {...{href}}>{image}</a> : image; } });

Page 75: Building the Media Block in ReactJS

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 = <img {...other} src={src}>; return href ? <a {...{href}}>{image}</a> : image; } });

get the responsive property

Page 76: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

Page 77: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

add this classif this evaluates

to true

Page 78: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

add this classif this evaluates

to true

then, put the class on the image

Page 79: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

Page 80: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

responsive has to be true or false

Page 81: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

Page 82: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

the href is a string

Page 83: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

Page 84: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

src is a string and required

Page 85: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

Page 86: Building the Media Block in ReactJS

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 = <img {...other} src={src} className={classes}>{children}</img>; return href ? <a {...{href}}>{image}</a> : image; } });

Page 87: Building the Media Block in ReactJS

OUR “AH-HA” MOMENTUsers are still needing to specify too many things to get this

component to work, they might as well just write html!

Page 88: Building the Media Block in ReactJS

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

Page 89: Building the Media Block in ReactJS

ELEMENTS FTWwe 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

Page 90: Building the Media Block in ReactJS

DESIGNERS ONLY USE 2 KINDS OF ALIGNMENT

❖ Traditional media with everything top aligned !

!

!

❖ “Flag” component a la Harry Roberts middle aligns

Page 91: Building the Media Block in ReactJS

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 <flag> component

<Flag leftImage={refreshImage}> refresh </Flag>

Page 92: Building the Media Block in ReactJS

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

Page 93: Building the Media Block in ReactJS

ARE ANY OF THESE WRONG?

No, absolutely not.

https://gist.github.com/stubbornella/e97662e4a197eb9a534a

Page 94: Building the Media Block in ReactJS

CHARTSloop 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

Page 95: Building the Media Block in ReactJS
Page 96: Building the Media Block in ReactJS

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' } ]

Page 97: Building the Media Block in ReactJS

TABS IN BOOTSTRAP<div role="tabpanel"> ! <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class=“active"> <a href="#home" aria-controls="home" role="tab" data-toggle=“tab">Home</a> </li> <li role=“presentation"> <a href="#profile" aria-controls="profile" role="tab" data-toggle=“tab”> Profile</a> </li> </ul> ! <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="home">...</div> <div role="tabpanel" class="tab-pane" id="profile">...</div> </div> !</div>

Page 98: Building the Media Block in ReactJS

TABS IN REACT

<SimpleTabs defaultActiveKey={1}> <Tab eventKey={1} tab="Home"> ... </Tab> <Tab eventKey={2} tab="Profile"> ... </Tab> </SimpleTabs>

Page 99: Building the Media Block in ReactJS

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-

r5vEd9-nkFqB2-4mbL7L-7VBztH

IT’S A DESIGN DECISION each component is different

Page 100: Building the Media Block in ReactJS

KEEP LOOPING BACKchange the interface until it works well

Page 101: Building the Media Block in ReactJS

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

Page 102: Building the Media Block in ReactJS

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-

pfkSRX-96twBn-6jrzx2-oAFqvC

Page 103: Building the Media Block in ReactJS

USE ALL THE TOOLS IN YOUR TOOLBOX

❖ Elements (built in and custom) ❖ Attributes (simple and objects) ❖ JSON ❖ Children

Page 104: Building the Media Block in ReactJS
Page 105: Building the Media Block in ReactJS

styleguide.pivotal.io

Page 106: Building the Media Block in ReactJS

WE OPEN SOURCED EVERYTHING

Please do give us feedback npm: https://www.npmjs.com/search?q=pui

github: github.com/pivotal-cf/pivotal-ui

Page 107: Building the Media Block in ReactJS

THANK YOU!@stubbornella