Building Loveable UIs

Building Loveable UIs

Some of the good and bad patterns when designing components in React. How to build scalable components keeping the visual consistency and good developer experience.

Presented at React Amsterdam 2016.

http://react.amsterdam

B39c4709d372f3f08a82f8e3700806f3?s=128

Henrique Alves

April 16, 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