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

Automating UI development

Automating UI development

Design systems and pattern libraries help designers and developers to get a common understanding of user interfaces. But even with such tools in place, there's a ton of processes and handovers involved. Each one causing possible friction and information loss. Especially over time. This might lead to new features feeling outdated on release, and screens and mock-ups getting too old too fast.

With our recent move to Angular and Sketch, we were able to automate 70% of our UI development. Helping our developers to focus on the real problems, and reducing the UI review efforts tremendously. Join us and see how we produce a single source of truth for developers and designers, and how we are able to consume this source in our tool of choice.

Stefan Baumgartner

November 06, 2018
Tweet

More Decks by Stefan Baumgartner

Other Decks in Technology

Transcript

  1. Automating UI
    Development
    Angular Connect 2018
    @ddprrt @Ka_TriN_F

    View full-size slide

  2. Slide about us
    Katrin Freihofner

    @Ka_TriN_F
    devone.at

    View full-size slide

  3. Slide about us
    Stefan Baumgartner

    @ddprrt
    javascript-podcast.com

    View full-size slide

  4. expert groups

    View full-size slide

  5. Highly specialised screens
    … with lots of generic, flexible components

    View full-size slide

  6. Git
    Design System update
    Symbols library

    View full-size slide

  7. Git
    Design System update
    Symbols library

    View full-size slide

  8. Design System update

    View full-size slide

  9. Design System update

    View full-size slide

  10. You might wonder
    …how will this affect the product?

    View full-size slide

  11. Initial idea

    View full-size slide

  12. UX + design
    Initial idea

    View full-size slide

  13. UX + design
    Initial idea
    Sketch lib

    View full-size slide

  14. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib

    View full-size slide

  15. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib
    Barista
    Design System

    View full-size slide

  16. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib
    Barista
    Design System

    View full-size slide

  17. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib
    Barista
    Design System

    View full-size slide

  18. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib
    Barista
    Design System

    View full-size slide

  19. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib
    Barista
    Design System

    View full-size slide

  20. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib
    Barista
    Design System

    View full-size slide

  21. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib
    Barista
    Design System

    View full-size slide

  22. Angular
    component lib

    View full-size slide

  23. Barista
    Design System
    Product
    code
    Angular
    component lib

    View full-size slide

  24. Barista
    Design System
    Product
    code
    ?
    Angular
    component lib

    View full-size slide

  25. Barista
    Design System
    Product
    code
    UX + design
    Sketch lib Angular
    component lib

    View full-size slide

  26. Transform Angular to Sketch
    Angular library Sketch library
    ?

    View full-size slide

  27. .sketch is bunch of JSON files
    library.sketch
    ʮ pages
    ʮ D91775B4-2C6C-4FCC-9209-6D8C930B9013.json
    ʮ document.json
    ʮ meta.json
    ʮ user.json

    View full-size slide

  28. .sketch is bunch of JSON files
    library.sketch
    ʮ pages
    ʮ D91775B4-2C6C-4FCC-9209-6D8C930B9013.json
    ʮ document.json
    ʮ meta.json
    ʮ user.json
    We can hack that!

    View full-size slide

  29. CSS equivalents in .sketch JSON
    button {
    width: 122px;
    height: 32px;
    background-color: #00f;
    }
    ShapeGroup: {
    frame: {x: 0, y: 0, width: 122, height: 32}
    layers: [
    ShapePath: {
    points: [‘{0,0}’,‘{0,1}’,‘{1,1}’,‘{1,0}’]
    }
    ],
    style: {
    fills: [
    color: {
    red: 0, green: 0, blue: 1, alpha: 1
    }
    ]
    }
    }

    View full-size slide

  30. CSS equivalents in .sketch JSON
    button {
    width: 122px;
    height: 32px;
    background-color: #00f;
    }
    ShapeGroup: {
    frame: {x: 0, y: 0, width: 122, height: 32}
    layers: [
    ShapePath: {
    points: [‘{0,0}’,‘{0,1}’,‘{1,1}’,‘{1,0}’]
    }
    ],
    style: {
    fills: [
    color: {
    red: 0, green: 0, blue: 1, alpha: 1
    }
    ]
    }
    }

    View full-size slide

  31. {
    "_class": "page",
    "do_objectID": "6224EB85-9573-4D33-BEE5-C57F892B94E4",
    "exportOptions": {
    "_class": "exportOptions",
    "exportFormats": [],
    "includedLayerIds": [],
    "layerOptions": 0,
    "shouldTrim": false
    },
    "frame": {
    "_class": "rect",
    "constrainProportions": false,
    "height": 300,
    "width": 300,
    "x": 0,
    "y": 0
    },
    "isFlippedHorizontal": false,
    CSS equivalents in .sketch JSON
    button {
    width: 122px;
    height: 32px;
    background-color: #00f;
    }

    View full-size slide

  32. CSS equivalents in .sketch JSON
    button {
    width: 122px;
    height: 32px;
    background-color: #00f;
    }

    View full-size slide

  33. parsable properties
    export class StyleDeclaration {
    borderTop = '0px none rgb(0, 0, 0)’; borderLeft = '0px none rgb(0, 0, 0)’;
    borderBottom = '0px none rgb(0, 0, 0)'; borderRight = '0px none rgb(0, 0, 0)';
    borderColor = 'rgb(0, 0, 0)'; borderTopLeftRadius = '0px';
    borderTopRightRadius = '0px'; borderBottomRightRadius = '0px';
    borderBottomLeftRadius = '0px'; borderWidth = '0px';
    boxShadow = 'none'; padding = '0px';
    backgroundImage = ‘none'; backgroundColor = 'rgba(0, 0, 0, 0)’; color = 'rgb(0, 0, 0)';
    fill = 'rgb(0, 0, 0)’; strokeWidth = '1px';
    fontFamily = 'Helvetica Neue'; fontSize = '16px'; fontStyle = 'normal'; fontWeight = '400';
    letterSpacing = ‘normal'; whiteSpace = ‘normal'; lineHeight = 'normal';
    textDecoration = 'none solid rgb(0, 0, 0)';
    textAlign = 'start'; textTransform = 'none'; transform = 'none';
    opacity = ‘1'; display = ‘block'; visibility = 'visible';
    }

    View full-size slide

  34. parsable properties
    export class StyleDeclaration {
    borderTop = '0px none rgb(0, 0, 0)’; borderLeft = '0px none rgb(0, 0, 0)’;
    borderBottom = '0px none rgb(0, 0, 0)'; borderRight = '0px none rgb(0, 0, 0)';
    borderColor = 'rgb(0, 0, 0)'; borderTopLeftRadius = '0px';
    borderTopRightRadius = '0px'; borderBottomRightRadius = '0px';
    borderBottomLeftRadius = '0px'; borderWidth = '0px';
    boxShadow = 'none'; padding = '0px';
    backgroundImage = ‘none'; backgroundColor = 'rgba(0, 0, 0, 0)’; color = 'rgb(0, 0, 0)';
    fill = 'rgb(0, 0, 0)’; strokeWidth = '1px';
    fontFamily = 'Helvetica Neue'; fontSize = '16px'; fontStyle = 'normal'; fontWeight = '400';
    letterSpacing = ‘normal'; whiteSpace = ‘normal'; lineHeight = 'normal';
    textDecoration = 'none solid rgb(0, 0, 0)';
    textAlign = 'start'; textTransform = 'none'; transform = 'none';
    opacity = ‘1'; display = ‘block'; visibility = 'visible';
    }

    View full-size slide

  35. parsable properties
    export class StyleDeclaration {
    borderTop = '0px none rgb(0, 0, 0)’; borderLeft = '0px none rgb(0, 0, 0)’;
    borderBottom = '0px none rgb(0, 0, 0)'; borderRight = '0px none rgb(0, 0, 0)';
    borderColor = 'rgb(0, 0, 0)'; borderTopLeftRadius = '0px';
    borderTopRightRadius = '0px'; borderBottomRightRadius = '0px';
    borderBottomLeftRadius = '0px'; borderWidth = '0px';
    boxShadow = 'none'; padding = '0px';
    backgroundImage = ‘none'; backgroundColor = 'rgba(0, 0, 0, 0)’; color = 'rgb(0, 0, 0)';
    fill = 'rgb(0, 0, 0)’; strokeWidth = '1px';
    fontFamily = 'Helvetica Neue'; fontSize = '16px'; fontStyle = 'normal'; fontWeight = '400';
    letterSpacing = ‘normal'; whiteSpace = ‘normal'; lineHeight = 'normal';
    textDecoration = 'none solid rgb(0, 0, 0)';
    textAlign = 'start'; textTransform = 'none'; transform = 'none';
    opacity = ‘1'; display = ‘block'; visibility = 'visible';
    }

    View full-size slide

  36. parsable properties
    export class StyleDeclaration {
    borderTop = '0px none rgb(0, 0, 0)’; borderLeft = '0px none rgb(0, 0, 0)’;
    borderBottom = '0px none rgb(0, 0, 0)'; borderRight = '0px none rgb(0, 0, 0)';
    borderColor = 'rgb(0, 0, 0)'; borderTopLeftRadius = '0px';
    borderTopRightRadius = '0px'; borderBottomRightRadius = '0px';
    borderBottomLeftRadius = '0px'; borderWidth = '0px';
    boxShadow = 'none'; padding = '0px';
    backgroundImage = ‘none'; backgroundColor = 'rgba(0, 0, 0, 0)’; color = 'rgb(0, 0, 0)';
    fill = 'rgb(0, 0, 0)’; strokeWidth = '1px';
    fontFamily = 'Helvetica Neue'; fontSize = '16px'; fontStyle = 'normal'; fontWeight = '400';
    letterSpacing = ‘normal'; whiteSpace = ‘normal'; lineHeight = 'normal';
    textDecoration = 'none solid rgb(0, 0, 0)';
    textAlign = 'start'; textTransform = 'none'; transform = 'none';
    opacity = ‘1'; display = ‘block'; visibility = 'visible';
    }

    View full-size slide

  37. parsable properties
    export class StyleDeclaration {
    borderTop = '0px none rgb(0, 0, 0)’; borderLeft = '0px none rgb(0, 0, 0)’;
    borderBottom = '0px none rgb(0, 0, 0)'; borderRight = '0px none rgb(0, 0, 0)';
    borderColor = 'rgb(0, 0, 0)'; borderTopLeftRadius = '0px';
    borderTopRightRadius = '0px'; borderBottomRightRadius = '0px';
    borderBottomLeftRadius = '0px'; borderWidth = '0px';
    boxShadow = 'none'; padding = '0px';
    backgroundImage = ‘none'; backgroundColor = 'rgba(0, 0, 0, 0)’; color = 'rgb(0, 0, 0)';
    fill = 'rgb(0, 0, 0)’; strokeWidth = '1px';
    fontFamily = 'Helvetica Neue'; fontSize = '16px'; fontStyle = 'normal'; fontWeight = '400';
    letterSpacing = ‘normal'; whiteSpace = ‘normal'; lineHeight = 'normal';
    textDecoration = 'none solid rgb(0, 0, 0)';
    textAlign = 'start'; textTransform = 'none'; transform = 'none';
    opacity = ‘1'; display = ‘block'; visibility = 'visible';
    }

    View full-size slide

  38. parsable properties
    export class StyleDeclaration {
    borderTop = '0px none rgb(0, 0, 0)’; borderLeft = '0px none rgb(0, 0, 0)’;
    borderBottom = '0px none rgb(0, 0, 0)'; borderRight = '0px none rgb(0, 0, 0)';
    borderColor = 'rgb(0, 0, 0)'; borderTopLeftRadius = '0px';
    borderTopRightRadius = '0px'; borderBottomRightRadius = '0px';
    borderBottomLeftRadius = '0px'; borderWidth = '0px';
    boxShadow = 'none'; padding = '0px';
    backgroundImage = ‘none'; backgroundColor = 'rgba(0, 0, 0, 0)’; color = 'rgb(0, 0, 0)';
    fill = 'rgb(0, 0, 0)’; strokeWidth = '1px';
    fontFamily = 'Helvetica Neue'; fontSize = '16px'; fontStyle = 'normal'; fontWeight = '400';
    letterSpacing = ‘normal'; whiteSpace = ‘normal'; lineHeight = 'normal';
    textDecoration = 'none solid rgb(0, 0, 0)';
    textAlign = 'start'; textTransform = 'none'; transform = 'none';
    opacity = ‘1'; display = ‘block'; visibility = 'visible';
    }

    View full-size slide

  39. parsable properties
    export class StyleDeclaration {
    borderTop = '0px none rgb(0, 0, 0)’; borderLeft = '0px none rgb(0, 0, 0)’;
    borderBottom = '0px none rgb(0, 0, 0)'; borderRight = '0px none rgb(0, 0, 0)';
    borderColor = 'rgb(0, 0, 0)'; borderTopLeftRadius = '0px';
    borderTopRightRadius = '0px'; borderBottomRightRadius = '0px';
    borderBottomLeftRadius = '0px'; borderWidth = '0px';
    boxShadow = 'none'; padding = '0px';
    backgroundImage = ‘none'; backgroundColor = 'rgba(0, 0, 0, 0)’; color = 'rgb(0, 0, 0)';
    fill = 'rgb(0, 0, 0)’; strokeWidth = '1px';
    fontFamily = 'Helvetica Neue'; fontSize = '16px'; fontStyle = 'normal'; fontWeight = '400';
    letterSpacing = ‘normal'; whiteSpace = ‘normal'; lineHeight = 'normal';
    textDecoration = 'none solid rgb(0, 0, 0)';
    textAlign = 'start'; textTransform = 'none'; transform = 'none';
    opacity = ‘1'; display = ‘block'; visibility = 'visible';
    }

    View full-size slide

  40. export class StyleDeclaration {
    borderTop = '0px none rgb(0, 0, 0)’; borderLeft = '0px none rgb(0, 0, 0)’;
    borderBottom = '0px none rgb(0, 0, 0)'; borderRight = '0px none rgb(0, 0, 0)';
    borderColor = 'rgb(0, 0, 0)'; borderTopLeftRadius = '0px';
    borderTopRightRadius = '0px'; borderBottomRightRadius = '0px';
    borderBottomLeftRadius = '0px'; borderWidth = '0px';
    boxShadow = 'none'; padding = '0px';
    backgroundImage = ‘none'; backgroundColor = 'rgba(0, 0, 0, 0)’; color = 'rgb(0, 0, 0)';
    fill = 'rgb(0, 0, 0)’; strokeWidth = '1px';
    fontFamily = 'Helvetica Neue'; fontSize = '16px'; fontStyle = 'normal'; fontWeight = '400';
    letterSpacing = ‘normal'; whiteSpace = ‘normal'; lineHeight = 'normal';
    textDecoration = 'none solid rgb(0, 0, 0)';
    textAlign = 'start'; textTransform = 'none'; transform = 'none';
    opacity = ‘1'; display = ‘block'; visibility = 'visible';
    }
    “browser stylesheet”

    View full-size slide

  41. CSS+HTML to Sketch

    + CSSStyleDeclaration

    + CSSStyleDeclaration

    + CSSStyleDeclaration


    "frame": {
    "_class": "rect",
    "constrainProportions":
    false,
    "height": 44,
    "width": 764,
    "x": 0,
    "y": 0
    },

    .json

    View full-size slide

  42. Transform Angular to Sketch
    Angular library Sketch library
    ? CSSDecl json
    Sketch Generator

    View full-size slide

  43. Generate CSS Declaration files
    CSS
    scraper

    View full-size slide

  44. Generate CSS Declaration files
    CSS
    scraper

    View full-size slide

  45. Generate CSS Declaration files
    CSS
    scraper

    View full-size slide

  46. Generate CSS Declaration files
    CSS
    scraper

    ➡ getComputedStyle()

    View full-size slide

  47. Generate CSS Declaration files
    CSS
    scraper

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    View full-size slide

  48. Generate CSS Declaration files
    CSS
    scraper

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    View full-size slide

  49. Generate CSS Declaration files
    CSS
    scraper

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    View full-size slide

  50. Generate CSS Declaration files
    CSS
    scraper

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    View full-size slide

  51. Generate CSS Declaration files
    CSS
    scraper

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()


    + CSSStyleDeclaration

    + CSSStyleDeclaration

    + CSSStyleDeclaration

    View full-size slide

  52. Generate CSS Declaration files
    CSS
    scraper

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    ➡ getComputedStyle()
    ➡ getBoundingClientRect()

    View full-size slide

  53. Generate CSS Declaration files
    CSS
    scraper

    View full-size slide

  54. Generate CSS Declaration files
    CSS
    scraper
    update!

    View full-size slide

  55. Generate CSS Declaration files
    CSS
    scraper
    update!

    View full-size slide

  56. Generate CSS Declaration files
    CSS
    scraper
    update!

    View full-size slide

  57. Transform angular to sketch
    Angular library Sketch library
    ? CSSDecl json
    Sketch Generator
    App
    CSS scraper

    View full-size slide

  58. Parsing component code
    Angular
    component lib

    View full-size slide

  59. TS
    Parsing component code
    Angular
    component lib
    Parses AST

    View full-size slide

  60. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    Parses AST

    View full-size slide

  61. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    examples

    View full-size slide

  62. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    @Component({
    moduleId: module.id,
    template: `Simple button`,
    })
    export class ButtonPureExampleComponent { }
    examples

    View full-size slide

  63. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    @Component({
    moduleId: module.id,
    template: `Simple button`,
    })
    export class ButtonPureExampleComponent { }
    examples

    View full-size slide

  64. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    @Component({
    moduleId: module.id,
    template: `Simple button`,
    })
    export class ButtonPureExampleComponent { }
    examples
    variants

    View full-size slide

  65. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    @Component({
    moduleId: module.id,
    template: `Simple button`,
    })
    export class ButtonPureExampleComponent { }
    @Component({
    selector: `button[dt-button], button[dt-icon-button]`,
    templateUrl: 'button.html',
    })
    export class DtButton extends … {
    @Input()
    get variant(): ‘primary’ | ‘secondary’ { return this._variant; }
    }
    examples
    variants

    View full-size slide

  66. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    @Component({
    moduleId: module.id,
    template: `Simple button`,
    })
    export class ButtonPureExampleComponent { }
    @Component({
    selector: `button[dt-button], button[dt-icon-button]`,
    templateUrl: 'button.html',
    })
    export class DtButton extends … {
    @Input()
    get variant(): ‘primary’ | ‘secondary’ { return this._variant; }
    }
    examples
    variants

    View full-size slide

  67. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    @Component({
    moduleId: module.id,
    template: `Simple button`,
    })
    export class ButtonPureExampleComponent { }
    @Component({
    selector: `button[dt-button], button[dt-icon-button]`,
    templateUrl: 'button.html',
    })
    export class DtButton extends … {
    @Input()
    get variant(): ‘primary’ | ‘secondary’ { return this._variant; }
    }
    examples
    variants

    View full-size slide

  68. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    @Component({
    moduleId: module.id,
    template: `Simple button`,
    })
    export class ButtonPureExampleComponent { }
    @Component({
    selector: `button[dt-button], button[dt-icon-button]`,
    templateUrl: 'button.html',
    })
    export class DtButton extends … {
    @Input()
    get variant(): ‘primary’ | ‘secondary’ { return this._variant; }
    }
    examples
    variants

    View full-size slide

  69. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    examples
    variants

    View full-size slide

  70. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    examples
    +
    variants

    View full-size slide

  71. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    examples
    +
    variants

    View full-size slide

  72. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    examples
    +
    variants

    View full-size slide

  73. A ‘pure’ example and component variants
    TS
    Angular
    component lib
    examples
    +
    variants

    View full-size slide

  74. Transform Angular to Sketch
    Angular library Sketch library
    CSSDecl json
    Sketch Generator
    App
    CSS
    scraper
    Library
    App
    generator

    View full-size slide

  75. UX + design
    Initial idea
    Angular
    component lib
    Product
    code
    Sketch lib
    Barista
    Design System

    View full-size slide

  76. Angular
    component lib
    Barista
    Design System
    Sketch lib
    Product
    code
    UX + design

    View full-size slide

  77. $royalblue-700: #393db0;
    dt-theme-palette($green-600,
    $green-700, $green-800),

    View full-size slide

  78. Lukas Holzer

    @luka5c0m

    View full-size slide

  79. Katrin Freihofner

    @Ka_TriN_F
    Stefan Baumgartner

    @ddprrt
    Office hours

    12:30 - 13:00

    View full-size slide