Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Automating UI development

555 views

Published on

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.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Automating UI development

  1. 1. Automating UI Development Angular Connect 2018 @ddprrt @Ka_TriN_F
  2. 2. Slide about usKatrin Freihofner
 @Ka_TriN_F devone.at
  3. 3. Slide about usStefan Baumgartner
 @ddprrt javascript-podcast.com
  4. 4. expert groups
  5. 5. Highly specialised screens … with lots of generic, flexible components
  6. 6. Git Design System update Symbols library
  7. 7. Git Design System update Symbols library
  8. 8. Design System update
  9. 9. Design System update
  10. 10. You might wonder …how will this affect the product?
  11. 11. Initial idea
  12. 12. UX + design Initial idea
  13. 13. UX + design Initial idea Sketch lib
  14. 14. UX + design Initial idea Angular component lib Product code Sketch lib
  15. 15. UX + design Initial idea Angular component lib Product code Sketch lib Barista Design System
  16. 16. UX + design Initial idea Angular component lib Product code Sketch lib Barista Design System
  17. 17. UX + design Initial idea Angular component lib Product code Sketch lib Barista Design System
  18. 18. UX + design Initial idea Angular component lib Product code Sketch lib Barista Design System
  19. 19. UX + design Initial idea Angular component lib Product code Sketch lib Barista Design System
  20. 20. UX + design Initial idea Angular component lib Product code Sketch lib Barista Design System
  21. 21. UX + design Initial idea Angular component lib Product code Sketch lib Barista Design System
  22. 22. Angular component lib
  23. 23. Barista Design System Product code Angular component lib
  24. 24. Barista Design System Product code ? Angular component lib
  25. 25. Barista Design System Product code UX + design Sketch lib Angular component lib
  26. 26. Transform Angular to Sketch Angular library Sketch library ?
  27. 27. .sketch is bunch of JSON files library.sketch pages D91775B4-2C6C-4FCC-9209-6D8C930B9013.json document.json meta.json user.json
  28. 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!
  29. 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 } ] } }
  30. 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 } ] } }
  31. 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; }
  32. 32. CSS equivalents in .sketch JSON button { width: 122px; height: 32px; background-color: #00f; }
  33. 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'; }
  34. 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'; }
  35. 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'; }
  36. 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'; }
  37. 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'; }
  38. 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'; }
  39. 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'; }
  40. 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”
  41. 41. CSS+HTML to Sketch <button …> + CSSStyleDeclaration <div …> + CSSStyleDeclaration <h1> + CSSStyleDeclaration … … "frame": { "_class": "rect", "constrainProportions": false, "height": 44, "width": 764, "x": 0, "y": 0 }, … .json
  42. 42. Transform Angular to Sketch Angular library Sketch library ? CSSDecl jsonSketch Generator
  43. 43. Generate CSS Declaration files CSS scraper
  44. 44. Generate CSS Declaration files CSS scraper
  45. 45. Generate CSS Declaration files CSS scraper <button …>
  46. 46. Generate CSS Declaration files CSS scraper <button …> ➡ getComputedStyle()
  47. 47. Generate CSS Declaration files CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect()
  48. 48. Generate CSS Declaration files CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …>
  49. 49. Generate CSS Declaration files CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …> ➡ getComputedStyle() ➡ getBoundingClientRect()
  50. 50. Generate CSS Declaration files CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …> ➡ getComputedStyle() ➡ getBoundingClientRect() <h1> ➡ getComputedStyle() ➡ getBoundingClientRect() …
  51. 51. Generate CSS Declaration files CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …> ➡ getComputedStyle() ➡ getBoundingClientRect() <h1> ➡ getComputedStyle() ➡ getBoundingClientRect() … <button …> + CSSStyleDeclaration <div …> + CSSStyleDeclaration <h1> + CSSStyleDeclaration …
  52. 52. Generate CSS Declaration files CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …> ➡ getComputedStyle() ➡ getBoundingClientRect() <h1> ➡ getComputedStyle() ➡ getBoundingClientRect() …
  53. 53. Generate CSS Declaration files CSS scraper
  54. 54. Generate CSS Declaration files CSS scraper update!
  55. 55. Generate CSS Declaration files CSS scraper update!
  56. 56. Generate CSS Declaration files CSS scraper update!
  57. 57. Transform angular to sketch Angular library Sketch library ? CSSDecl jsonSketch GeneratorApp CSS scraper
  58. 58. Parsing component code Angular component lib
  59. 59. TS Parsing component code Angular component lib Parses AST
  60. 60. A ‘pure’ example and component variants TSAngular component lib Parses AST
  61. 61. A ‘pure’ example and component variants TSAngular component lib examples
  62. 62. A ‘pure’ example and component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</button>`, }) export class ButtonPureExampleComponent { } examples
  63. 63. A ‘pure’ example and component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</button>`, }) export class ButtonPureExampleComponent { } examples
  64. 64. A ‘pure’ example and component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</button>`, }) export class ButtonPureExampleComponent { } examples variants
  65. 65. A ‘pure’ example and component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</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
  66. 66. A ‘pure’ example and component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</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
  67. 67. A ‘pure’ example and component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</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
  68. 68. A ‘pure’ example and component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</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
  69. 69. A ‘pure’ example and component variants TSAngular component lib examples variants
  70. 70. A ‘pure’ example and component variants TSAngular component lib examples + variants
  71. 71. A ‘pure’ example and component variants TSAngular component lib examples + variants
  72. 72. A ‘pure’ example and component variants TSAngular component lib examples + variants
  73. 73. A ‘pure’ example and component variants TSAngular component lib examples + variants
  74. 74. Transform Angular to Sketch Angular library Sketch libraryCSSDecl json Sketch GeneratorApp CSS scraper Library App generator
  75. 75. UX + design Initial idea Angular component lib Product code Sketch lib Barista Design System
  76. 76. Angular component lib Barista Design System Sketch lib Product code UX + design
  77. 77. $royalblue-700: #393db0; dt-theme-palette($green-600, $green-700, $green-800),
  78. 78. Lukas Holzer
 @luka5c0m
  79. 79. Katrin Freihofner
 @Ka_TriN_F Stefan Baumgartner
 @ddprrt Office hours
 12:30 - 13:00

×