Henrique Alves, DADI+, London — Building Loveable UIs

Henrique Alves, DADI+, London — Building Loveable UIs

Henrique Alves, DADI+, London — Building Loveable UIs

Sharing my experience building loveable UIs. Talking about presentational components and pattern types for build scalable web apps in React.

5799a3c0434b91ef7e00e730629390f0?s=128

React Amsterdam

April 21, 2016
Tweet

Transcript

  1. BUILDING ABLE UIS REACT AMSTERDAM 2016 @HEALVES82

  2. DEVELOPER EXPERIENCE WHEN BUILDING PRODUCTS

  3. BEFORE REACT…

  4. <i class="marker-icon express big"> <span class="marker-arrow"></span> </i>

  5. // home.scss @import "variables"; @import "components/header"; @import "components/footer";
 @import "components/buttons";

    @import "pages/home";
  6. HTML WEB PAGE
 DOCUMENT JS CSS PDD PAGE DRIVEN DEVELOPMENT

  7. HTML MARKUP HOLY GRAIL OF 
 WEBMASTER JS UI CSS

    STYLING – THE EARLY DAYS –
  8. None
  9. MARKUP, JAVASCRIPT AND STYLING 
 COMPOSES THE UI

  10. MARKUP HTML/JSX STYLING CSS/INLINE JAVASCRIPT UI

  11. NOWADAYS…

  12. BUILDING AMBITIOUS USER INTERFACES REACT IS A LIBRARY FOR

  13. COMPONENTS ARE THE BUILDING BLOCKS OF AN APP

  14. DESIGNING COMPONENTS — ENCAPSULATION — COMPOSITION

  15. ENCAPSULATION — SELF CONTAINED — DOESN’T CARE ABOUT DATA —

    NO ACCESS TO APP’S STATE
  16. const StaticReadingList = () => ( // Let's render only

    one item <ReadingItem headline="The End of Ice" subHeadline="The New Yorker" description={ `A team of scientists hikes to investigate how quickly its ice is melting.` } imageSrc="//cldup.com/1rbk08vtLj.jpg" /> );
  17. GITHUB.COM/RECON-JS/RECON

  18. ENCAPSULATION EASY TO REUSE, MAINTAIN AND TEST.

  19. COMPOSITION — COMBINING ELEMENTS — BUILDING BLOCKS <Headline level={2} />

    <Text color="gray88" />
  20. const ReadingItem = ({headline, description, imageSrc}) => ( <Box> <Box

    flex="0 0 55%"> <Headline level={2}>{headline}</Headline> <Text element="p">{description}</Text> <Link href="#">Read Article</Link> </Box> <Box flex="1 0 45%"> <Image width="100%" src={imageSrc} /> </Box> </Box> );
  21. COMPOSITION ENCAPSULATION DEVELOPER EXPERIENCE – and –

  22. DOCUMENT YOUR COMPONENTS

  23. JXNBLK.COM/REBASS

  24. VISUAL CONSISTENCY
 COMES FOR FREE * * NOT ALWAYS

  25. GETTING THERE

  26. DESIGN COMPONENTS NOT PAGES

  27. LEARN HOW TO ABSTRACT.
 BORROW CONCEPTS.
 — ATOMIC DESIGN —

    CONTENT & DISPLAY PATTERNS — FUNCTIONAL CSS
  28. <Headline level={5} /> // <h5> <Text element="p" /> // <p>

    <Headline level={2} /> // <h2> <Link /> // <a> <ReadingItem headline="Article Title" subHeadline="Site Name" description="Random copy" imageSrc="thumb.jpg" /> <Box element="article" /> // <article>
  29. LOW LEVEL COMPONENTS

  30. // layout.js export const Box = ({ element: Element =

    'div', children, ...otherProps }) => ( <Element {...otherProps} style={composeStyle(otherProps)}> {children} </Element> );
  31. // layout.js // compose style object from props function composeStyle({style,

    ...otherProps}) { const bodyStyle = document.body.style; return { ...pickBy((v, k) => bodyStyle.hasOwnProperty(k), otherProps), ...style }; }
  32. NAMING IS HARD

  33. NAMING IS HARD — CONTENT-BASED NAMES — VISUAL NAMES —

    FUNCTIONAL NAMES
  34. NAMING COMPONENTS COOL NOT COOL <Card />
 <Headline /> <Headline

    level={1} />
 <Link /> <ImageCard />
 <StoryTitle /> <MasterHeadline /> <StoryLink />
  35. CONTENT-BASED NAMES THE CONTENT THEY CONTAIN. <UserStatus online={true} />

  36. VISUAL NAMES STYLING AND LOOKING.

  37. <Headline level={5} color="#9E9E9E" fontWeight={500} theme="dark" {...otherProps} > {text} </Headline>

  38. FUNCTIONAL NAMES THEIR FUNCTION OR UTILITY. <Resizable width={300}> {/* Menu

    list */} </Resizable>
  39. CONTAINER PRESENTATIONAL – and –

  40. <ReadingListPage /> CONTAINER TALKS TO STORES <ReadingList /> PRESENTATIONAL RENDER

    MARKUP
  41. CONTAINER — NO MARKUP OR STYLING
 — OFTEN STATEFUL
 —

    SERVE AS DATA SOURCES
  42. class ReadingListPage extends Component { constructor(props) { super(props); this.state =

    {data: []}; } componentWillMount() { fetch('http://localhost:8000/reading-list.json') .then((response) => { if (response.status >= 400) { return Promise.reject(new Error('Something went wrong!')); } return response.json(); }) .then((stories) => this.setState({data: stories})); } render() { const {data} = this.state; return <ReadingList data={data} /> } }
  43. PRESENTATIONAL — MARKUP AND STYLING
 — NO STATE
 — OFTEN

    FUNCTIONAL COMPONENTS
  44. const ReadingList = ({data}) => ( <ul> {data.map( (story, key)

    => ( <li key={key}> <ReadingItem headline={story.headline} subHeadline={story.site} description={story.description} imageSrc={story.imageSrc} /> </li> ) )} </ul> );
  45. PURE COMPONENTS 
 — CLASS OR FUNCTION
 — OFTEN PURE

    FUNCTIONS
 — STATELESS
  46. const Text = ({children}) => <span>{children}</span>;

  47. CLASSES FUNCTIONS – or –

  48. CLASSES COMPONENTS 
 — STATES
 — LIFECYCLE HOOKS componentWillMount()
 —

    OPTIMISED shallowCompare()
  49. SHALLOW COMPARE // react-addons-shallow-compare shouldComponentUpdate(nextProps, nextState) { return shallowCompare(this, nextProps,

    nextState); } // Using immutable objects shouldComponentUpdate(nextProps) { // Avoid object deep comparison return this.props.title !== nextProps.title }
  50. FUNCTIONAL COMPONENTS — NO SIDE EFFECTS
 — GOOD TO BUILD

    ABSTRACTIONS
 — WORKS IN SMALL AND LARGE
  51. CLASSES FUNCTIONS – or – — STATELESS FUNCTIONS WHEN POSSIBLE


    — UNDERSTAND THE DRAWBACKS — HAVE FUN
  52. INLINE STYLES • HERE TO STAY • – SINCE 2013

    ? –
  53. INLINE STYLES — EASY TO BUNDLE — CONSTANTS
 — PRIVATE

    BY DEFAULT
  54. const CONTENT_SPACING = 15; const BORDER_RADIUS = 3; const styles

    = { padding: CONTENT_SPACING, borderRadius: BORDER_RADIUS, width: 500, flexDirection: 'row', flexWrap: 'wrap', overflow: 'hidden', backgroundColor: '#fff', boxShadow: 'rgba(0, 0, 0, 0.0470588) 0px 2px 3px 0px' };
  55. ANIMATION IMPROVE THE USABILITY FEELS NATURAL
 GIVE FEEDBACK

  56. const ReadingItem = ({animate, headline, description, imageSrc}) => ( <Animate

    animate={animate}> <Box> <Box flex="0 0 55%"> <Headline level={2}>{headline}</Headline> <Text element="p">{description}</Text> <Link href="#">Read Article</Link> </Box> <Box flex="1 0 45%"> <Image width="100%" src={imageSrc} /> </Box> </Box> </Animate> );
  57. // animate.js const styles = { root: { position: 'relative',

    zIndex: 2, transition: 'all 1s cubic-bezier(.75,.1,.1,1)', transformStyle: 'preserve-3d', transform: 'translateX(-1000px) rotate(30deg) translateY(1000px)', visibility: 'hidden' }, animate: { transform: 'translateZ(0)', visibility: 'visible' } }; const Animate = ({children, animate}) => { const style = Object.assign({}, styles.root, animate && styles.animate ); return <Box style={style}>{children}</Box>; }
  58. <Animate animate={true} engine="react-motion"> {/* ... */} </Animate>

  59. FUTURE REACT? – of –

  60. REACT-FUTURE * 
 — ANIMATION — GESTURES
 — LAYOUT SYSTEM

    (DEPENDS ON INLINE STYLING) * GITHUB.COM/REACTJS/REACT-FUTURE
  61. LINKS & REFERENCES GITHUB.COM/HENRIQUEA/REACT-AMSTERDAM-2016-TALK GITHUB.COM/REACTJS/REACT-FUTURE GITHUB.COM/RECON-JS/RECON GITHUB.COM/KADIRAHQ/REACT-STORYBOOK GITHUB.COM/SKIDDING/COSMOS GITHUB.COM/SCUP/ATELLIER DANIELMALL.COM/ARTICLES/CONTENT-DISPLAY-PATTERNS

    BRADFROST.COM/BLOG/POST/ATOMIC-WEB-DESIGN PATTERNLAB.IO JON.GOLD/2015/07/FUNCTIONAL-CSS MEDIUM.COM/@DAN_ABRAMOV/SMART-AND-DUMB-COMPONENTS-7CA2F9A7C7D0 JXNBLK.COM/REBASS GITHUB.COM/CHENGLOU/REACT-MOTION GITHUB.COM/JSSTYLES/JSS GITHUB.COM/CSS-MODULES/CSS-MODULES
  62. DANK U @HEALVES82 #REACTAMSTERDAM