Automating UI
Development
Angular Connect 2018
@ddprrt @Ka_TriN_F
Slide about usKatrin Freihofner

@Ka_TriN_F
devone.at
Slide about usStefan Baumgartner

@ddprrt
javascript-podcast.com
expert groups
Highly specialised screens
… with lots of generic, flexible components
Git
Design System update
Symbols library
Git
Design System update
Symbols library
Design System update
Design System update
You might wonder
…how will this affect the product?
Initial idea
UX + design
Initial idea
UX + design
Initial idea
Sketch lib
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
Barista
Design System
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
Barista
Design System
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
Barista
Design System
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
Barista
Design System
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
Barista
Design System
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
Barista
Design System
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
Barista
Design System
Angular
component lib
Barista
Design System
Product
code
Angular
component lib
Barista
Design System
Product
code
? Angular
component lib
Barista
Design System
Product
code
UX + design
Sketch lib Angular
component lib
Transform Angular to Sketch
Angular library Sketch library
?
.sketch is bunch of JSON files
library.sketch
pages
D91775B4-2C6C-4FCC-9209-6D8C930B9013.json
document.json
meta.json
user.json
.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!
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
}
]
}
}
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
}
]
}
}
{
"_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;
}
CSS equivalents in .sketch JSON
button {
width: 122px;
height: 32px;
background-color: #00f;
}
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';
}
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';
}
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';
}
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';
}
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';
}
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';
}
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';
}
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”
CSS+HTML to Sketch
<button …>
+ CSSStyleDeclaration
<div …>
+ CSSStyleDeclaration
<h1>
+ CSSStyleDeclaration
…
…
"frame": {
"_class": "rect",
"constrainProportions":
false,
"height": 44,
"width": 764,
"x": 0,
"y": 0
},
…
.json
Transform Angular to Sketch
Angular library Sketch library
? CSSDecl jsonSketch Generator
Generate CSS Declaration files
CSS
scraper
Generate CSS Declaration files
CSS
scraper
Generate CSS Declaration files
CSS
scraper
<button …>
Generate CSS Declaration files
CSS
scraper
<button …>
➡ getComputedStyle()
Generate CSS Declaration files
CSS
scraper
<button …>
➡ getComputedStyle()
➡ getBoundingClientRect()
Generate CSS Declaration files
CSS
scraper
<button …>
➡ getComputedStyle()
➡ getBoundingClientRect()
<div …>
Generate CSS Declaration files
CSS
scraper
<button …>
➡ getComputedStyle()
➡ getBoundingClientRect()
<div …>
➡ getComputedStyle()
➡ getBoundingClientRect()
Generate CSS Declaration files
CSS
scraper
<button …>
➡ getComputedStyle()
➡ getBoundingClientRect()
<div …>
➡ getComputedStyle()
➡ getBoundingClientRect()
<h1>
➡ getComputedStyle()
➡ getBoundingClientRect()
…
Generate CSS Declaration files
CSS
scraper
<button …>
➡ getComputedStyle()
➡ getBoundingClientRect()
<div …>
➡ getComputedStyle()
➡ getBoundingClientRect()
<h1>
➡ getComputedStyle()
➡ getBoundingClientRect()
…
<button …>
+ CSSStyleDeclaration
<div …>
+ CSSStyleDeclaration
<h1>
+ CSSStyleDeclaration
…
Generate CSS Declaration files
CSS
scraper
<button …>
➡ getComputedStyle()
➡ getBoundingClientRect()
<div …>
➡ getComputedStyle()
➡ getBoundingClientRect()
<h1>
➡ getComputedStyle()
➡ getBoundingClientRect()
…
Generate CSS Declaration files
CSS
scraper
Generate CSS Declaration files
CSS
scraper
update!
Generate CSS Declaration files
CSS
scraper
update!
Generate CSS Declaration files
CSS
scraper
update!
Transform angular to sketch
Angular library Sketch library
? CSSDecl jsonSketch GeneratorApp CSS scraper
Parsing component code
Angular
component lib
TS
Parsing component code
Angular
component lib
Parses AST
A ‘pure’ example and component variants
TSAngular
component lib
Parses AST
A ‘pure’ example and component variants
TSAngular
component lib
examples
A ‘pure’ example and component variants
TSAngular
component lib
@Component({
moduleId: module.id,
template: `<button dt-button>Simple button</button>`,
})
export class ButtonPureExampleComponent { }
examples
A ‘pure’ example and component variants
TSAngular
component lib
@Component({
moduleId: module.id,
template: `<button dt-button>Simple button</button>`,
})
export class ButtonPureExampleComponent { }
examples
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
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
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
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
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
A ‘pure’ example and component variants
TSAngular
component lib
examples
variants
A ‘pure’ example and component variants
TSAngular
component lib
examples
+
variants
A ‘pure’ example and component variants
TSAngular
component lib
examples
+
variants
A ‘pure’ example and component variants
TSAngular
component lib
examples
+
variants
A ‘pure’ example and component variants
TSAngular
component lib
examples
+
variants
Transform Angular to Sketch
Angular library Sketch libraryCSSDecl json
Sketch GeneratorApp
CSS
scraper
Library
App
generator
UX + design
Initial idea
Angular
component lib
Product
code
Sketch lib
Barista
Design System
Angular
component lib
Barista
Design System
Sketch lib
Product
code
UX + design
$royalblue-700: #393db0;
dt-theme-palette($green-600,
$green-700, $green-800),
Lukas Holzer

@luka5c0m
Katrin Freihofner

@Ka_TriN_F
Stefan Baumgartner

@ddprrt
Office hours

12:30 - 13:00

Automating UI development

  • 1.
  • 2.
    Slide about usKatrinFreihofner
 @Ka_TriN_F devone.at
  • 3.
    Slide about usStefanBaumgartner
 @ddprrt javascript-podcast.com
  • 7.
  • 8.
    Highly specialised screens …with lots of generic, flexible components
  • 18.
  • 19.
  • 20.
  • 21.
  • 23.
    You might wonder …howwill this affect the product?
  • 25.
  • 26.
  • 27.
    UX + design Initialidea Sketch lib
  • 28.
    UX + design Initialidea Angular component lib Product code Sketch lib
  • 29.
    UX + design Initialidea Angular component lib Product code Sketch lib Barista Design System
  • 30.
    UX + design Initialidea Angular component lib Product code Sketch lib Barista Design System
  • 31.
    UX + design Initialidea Angular component lib Product code Sketch lib Barista Design System
  • 32.
    UX + design Initialidea Angular component lib Product code Sketch lib Barista Design System
  • 33.
    UX + design Initialidea Angular component lib Product code Sketch lib Barista Design System
  • 34.
    UX + design Initialidea Angular component lib Product code Sketch lib Barista Design System
  • 35.
    UX + design Initialidea Angular component lib Product code Sketch lib Barista Design System
  • 39.
  • 40.
  • 41.
  • 42.
    Barista Design System Product code UX +design Sketch lib Angular component lib
  • 43.
    Transform Angular toSketch Angular library Sketch library ?
  • 44.
    .sketch is bunchof JSON files library.sketch pages D91775B4-2C6C-4FCC-9209-6D8C930B9013.json document.json meta.json user.json
  • 45.
    .sketch is bunchof JSON files library.sketch pages D91775B4-2C6C-4FCC-9209-6D8C930B9013.json document.json meta.json user.json We can hack that!
  • 46.
    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 } ] } }
  • 47.
    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 } ] } }
  • 48.
    { "_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; }
  • 49.
    CSS equivalents in.sketch JSON button { width: 122px; height: 32px; background-color: #00f; }
  • 50.
    parsable properties export classStyleDeclaration { 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'; }
  • 51.
    parsable properties export classStyleDeclaration { 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'; }
  • 52.
    parsable properties export classStyleDeclaration { 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'; }
  • 53.
    parsable properties export classStyleDeclaration { 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'; }
  • 54.
    parsable properties export classStyleDeclaration { 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'; }
  • 55.
    parsable properties export classStyleDeclaration { 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'; }
  • 56.
    parsable properties export classStyleDeclaration { 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'; }
  • 57.
    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”
  • 58.
    CSS+HTML to Sketch <button…> + CSSStyleDeclaration <div …> + CSSStyleDeclaration <h1> + CSSStyleDeclaration … … "frame": { "_class": "rect", "constrainProportions": false, "height": 44, "width": 764, "x": 0, "y": 0 }, … .json
  • 59.
    Transform Angular toSketch Angular library Sketch library ? CSSDecl jsonSketch Generator
  • 60.
    Generate CSS Declarationfiles CSS scraper
  • 61.
    Generate CSS Declarationfiles CSS scraper
  • 62.
    Generate CSS Declarationfiles CSS scraper <button …>
  • 63.
    Generate CSS Declarationfiles CSS scraper <button …> ➡ getComputedStyle()
  • 64.
    Generate CSS Declarationfiles CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect()
  • 65.
    Generate CSS Declarationfiles CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …>
  • 66.
    Generate CSS Declarationfiles CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …> ➡ getComputedStyle() ➡ getBoundingClientRect()
  • 67.
    Generate CSS Declarationfiles CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …> ➡ getComputedStyle() ➡ getBoundingClientRect() <h1> ➡ getComputedStyle() ➡ getBoundingClientRect() …
  • 68.
    Generate CSS Declarationfiles CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …> ➡ getComputedStyle() ➡ getBoundingClientRect() <h1> ➡ getComputedStyle() ➡ getBoundingClientRect() … <button …> + CSSStyleDeclaration <div …> + CSSStyleDeclaration <h1> + CSSStyleDeclaration …
  • 69.
    Generate CSS Declarationfiles CSS scraper <button …> ➡ getComputedStyle() ➡ getBoundingClientRect() <div …> ➡ getComputedStyle() ➡ getBoundingClientRect() <h1> ➡ getComputedStyle() ➡ getBoundingClientRect() …
  • 70.
    Generate CSS Declarationfiles CSS scraper
  • 71.
    Generate CSS Declarationfiles CSS scraper update!
  • 72.
    Generate CSS Declarationfiles CSS scraper update!
  • 73.
    Generate CSS Declarationfiles CSS scraper update!
  • 74.
    Transform angular tosketch Angular library Sketch library ? CSSDecl jsonSketch GeneratorApp CSS scraper
  • 75.
  • 76.
  • 77.
    A ‘pure’ exampleand component variants TSAngular component lib Parses AST
  • 78.
    A ‘pure’ exampleand component variants TSAngular component lib examples
  • 79.
    A ‘pure’ exampleand component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</button>`, }) export class ButtonPureExampleComponent { } examples
  • 80.
    A ‘pure’ exampleand component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</button>`, }) export class ButtonPureExampleComponent { } examples
  • 81.
    A ‘pure’ exampleand component variants TSAngular component lib @Component({ moduleId: module.id, template: `<button dt-button>Simple button</button>`, }) export class ButtonPureExampleComponent { } examples variants
  • 82.
    A ‘pure’ exampleand 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
  • 83.
    A ‘pure’ exampleand 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
  • 84.
    A ‘pure’ exampleand 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
  • 85.
    A ‘pure’ exampleand 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
  • 86.
    A ‘pure’ exampleand component variants TSAngular component lib examples variants
  • 87.
    A ‘pure’ exampleand component variants TSAngular component lib examples + variants
  • 88.
    A ‘pure’ exampleand component variants TSAngular component lib examples + variants
  • 89.
    A ‘pure’ exampleand component variants TSAngular component lib examples + variants
  • 90.
    A ‘pure’ exampleand component variants TSAngular component lib examples + variants
  • 91.
    Transform Angular toSketch Angular library Sketch libraryCSSDecl json Sketch GeneratorApp CSS scraper Library App generator
  • 94.
    UX + design Initialidea Angular component lib Product code Sketch lib Barista Design System
  • 95.
  • 98.
  • 102.
  • 103.