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

Tasty Atomic.Fusion recipes for your website - NeosConference 2018

Tasty Atomic.Fusion recipes for your website - NeosConference 2018

Sitegeist

April 14, 2018
Tweet

More Decks by Sitegeist

Other Decks in Programming

Transcript

  1. Real Values.
    Tasty Atomic.Fusion recipes for your website
    Martin Ficzel

    View full-size slide

  2. Real Values.
    Martin Ficzel
    ● Backend Developer
    [email protected]
    ● twitter/slack: @kopfaufholz
    ● Neos Team-Member
    Atomic-Fusion, AFX
    ● Sitegeist.Monocle
    ● 2 Kids, Climber

    View full-size slide

  3. Real Values.
    !!! Tons of code ahead

    View full-size slide

  4. Real Values.
    Terms

    View full-size slide

  5. Real Values.
    AFX

    View full-size slide

  6. Real Values.
    AFX
    renderer = afx`

    {props.title}
    {props.subtitle}


    `

    View full-size slide

  7. Real Values.
    Fusion
    renderer = Neos.Fusion:Tag {
    tagName = 'div'
    content = Neos.Fusion:Array {
    item_1 = Neos.Fusion:Tag {
    tagName = 'h1'
    content = ${props.title}
    attributes.class = 'headline'
    }
    item_2 = Neos.Fusion:Tag {
    tagName = 'h2'
    content = ${props.subtitle}
    attributes.subheadline = 'subheadline'
    @if.hasSubtitle = ${props.subtitle ? true : false}
    }
    Vendor.Site:Image {

    View full-size slide

  8. Real Values.
    AFX
    Fusion, optimized for presentation
    ● Easy to read and declarative
    ● Usable without Atomic.Fusion
    ● Makes Fluid obsolete
    ● Eliminates a lot of jumping back
    and forth between templates and
    fusion
    ● No negative runtime effects

    View full-size slide

  9. Real Values.
    Neos.Fusion.AFX
    composer require neos/fusion-afx

    View full-size slide

  10. Real Values.
    Atomic.Fusion

    View full-size slide

  11. Real Values.
    Fusion
    ● Neos.Fusion:Component
    ● Neos.Fusion:Augmenter
    Neos
    ● Neos.Neos:ContentComponent
    ● Neos.Neos:Editable
    Prototypes

    View full-size slide

  12. Real Values.
    ● Separation
    of Presentation and Integration
    ● Isolation
    of all visual aspects in
    presentational components
    Principles
    for structuring projects

    View full-size slide

  13. Real Values.
    Atomic.Fusion is an advanced concept!

    View full-size slide

  14. Real Values.
    Patterns for Presentation

    View full-size slide

  15. Real Values.
    Presentational Component

    View full-size slide

  16. Real Values.
    Presentational Component
    prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Component)
    {
    title = ''
    description = ''
    renderer = afx`

    {props.title}
    {props.description}

    `

    View full-size slide

  17. Real Values.
    Definition
    ● Presentational components
    encapsulate the visual aspects for
    the representation of a data
    structure. This includes the
    generation of markup, styling and
    interaction via scripts.
    ● Presentational components are
    side effect free but may rely on
    other presentational components
    to perform their job.

    View full-size slide

  18. Real Values.
    Composition

    View full-size slide

  19. Real Values.
    Composition
    prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Component)
    {
    title = ''
    description = ''
    imageUri = null
    renderer = afx`


    {props.title}
    {props.description}

    View full-size slide

  20. Real Values.
    Flag

    View full-size slide

  21. Real Values.
    Flags
    prototype(Vendor.Site:Component.Atom.Headline) < prototype(Neos.Fusion:Component) {
    title = null
    isSpecial = false
    renderer = afx`
    {props.title}
    `
    }

    View full-size slide

  22. Real Values.
    Modifier

    View full-size slide

  23. Real Values.
    Modifier
    prototype(Vendor.Site:Component.Atom.Headline) < prototype(Neos.Fusion:Component) {
    title = null
    modifier = null
    renderer = afx`
    {props.title}
    `
    @propTypes {
    modifier = ${PropTypes.oneOf('bold', 'italic')}
    }
    }

    View full-size slide

  24. Real Values.
    Augment

    View full-size slide

  25. Real Values.
    Augmentation
    prototype(Vendor.Site:Component.Molecule.TeaserList) < prototype(Neos.Fusion:Componen
    renderer = afx`

    data-filter-region={teaser.region}
    data-filter-category={teaser.category}
    class=”teaserlist__item”
    >
    />

    ...
    iv>

    View full-size slide

  26. Real Values.
    Conditional Tagname

    View full-size slide

  27. Real Values.
    Conditional Tagname
    prototype(Vendor.Site:Component.Atom.Button) < prototype(Neos.Fusion:Component) {
    link = null
    title = null
    renderer = afx`
    tagName={props.link ? 'a' : 'span'}
    href={props.link}
    attributes.class="button"
    >
    {props.title}

    View full-size slide

  28. Real Values.
    Optional Section

    View full-size slide

  29. Real Values.
    Optional Section
    prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Compone
    title = ''
    subtitle = ''
    renderer = afx`

    {props.title}

    {props.subtitle}


    `
    }

    View full-size slide

  30. Real Values.
    Collection

    View full-size slide

  31. Real Values.
    Collection
    prototype(Vendor.Site:Component.Molecule.Slider) < prototype(Neos.Fusion:Component) {
    // [ {title: 'lorem', href: 'http://dummyimage.com' }, ... ]
    items = null
    renderer = afx`

    collection={props.items}
    itemName="item"
    @children="itemRenderer"
    >


    /Vendor.Site:Component.Molecule.Slider.Slide>

    View full-size slide

  32. Real Values.
    Container

    View full-size slide

  33. Real Values.
    Container
    prototype(Vendor.Site:Component.Molecule.Accordeon) < prototype(Neos.Fusion:Compone
    title = ''
    content = ''
    renderer = afx`

    {props.title}
    {props.content}

    `
    }

    View full-size slide

  34. Real Values.
    Container - content
    prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Component) {
    renderer = afx`

    Lorem ipsum

    `
    }

    View full-size slide

  35. Real Values.

    View full-size slide

  36. Real Values.
    Component APIs

    View full-size slide

  37. Real Values.
    Presentational Component APIs
    ● Mainly simple values / Meaningful Names
    ● “content” is a nice name for a html string
    ● Complex Data
    ○ Collections
    ○ Hashmaps
    ● !!! never pass domain objects
    ○ Convert to simple values like uris instead

    View full-size slide

  38. Real Values.
    WWJD?

    View full-size slide

  39. Real Values.
    What Would JSON Do

    View full-size slide

  40. Real Values.
    Additional Tools
    for Presentation

    View full-size slide

  41. Real Values.
    Sitegeist.Monocle
    prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Component) {
    @styleguide {
    title = 'Example Component'
    props {
    title = 'Lorem ipsum'
    description = 'dolor sit amet ...'
    imageUri = '//dummyimage.com/600x400/000/fff'
    }
    }
    }
    composer require
    sitegeist/monocle

    View full-size slide

  42. Real Values.
    PropTypes
    prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Component) {
    @propTypes {
    title = ${PropTypes.string.isRequired}
    description = ${PropTypes.string}
    imageUri = ${PropTypes.string}
    }
    }
    composer require
    packagefactory/atomicfusion-proptypes

    View full-size slide

  43. Real Values.
    Structuring the
    namespace

    View full-size slide

  44. Real Values.
    Atomic Design
    ● Bottom up - principle
    ● Atoms, Molecules, Organism,
    Template
    ● Seldomly used for design but often
    used to structure code
    ● !!! Effective way to find
    inconsistencies in design via
    coding

    View full-size slide

  45. Real Values.
    Your Method!
    The recommended way
    ● Reflects your design process and
    intention
    ● Common knowledge of your team
    members
    ● Ubiquitous Language between FE
    and BE
    ● Start where you are!

    View full-size slide

  46. Real Values.
    Snowflake
    Method
    ● Top down
    ● Take whole layout
    ● Split into parts
    ● Repeat the last step
    ● !!! Naming things is hard
    ● !!! Finding the granularity is hard

    View full-size slide

  47. Real Values.
    Be pragmatic
    there is no final structure
    ● Talk to designers
    ● Use parts of Atomic.Design or
    other design systems that fit
    ● Mind your future self
    ● Iterate

    View full-size slide

  48. Real Values.

    View full-size slide

  49. Real Values.
    Patterns for Integration

    View full-size slide

  50. Real Values.
    Hidden secrets of Neos

    View full-size slide

  51. Real Values.
    Secret 1: NodeType >> Fusion Prototype
    type = ${q(node).property('_nodeType.name')}

    View full-size slide

  52. Real Values.
    Secret 2: PrototypeGenerator
    #
    # Disable automagic fusion prototypes
    #
    Vendor.Site:Content.Example:
    options:
    fusion:
    prototypeGenerator: ~

    View full-size slide

  53. Real Values.

    data-__neos-node-contextpath="/sites/sitegeistde/main/node-j3xwsoeihfthx@
    data-__neos-fusion-path="page/body>


    data-__neos-property="title"
    data-__neos-editable-node-contextpath="/sites/sitegeistde/main/no
    >
    Lorem ipsum dolor sit amet

    Neos Secret 3: Backend Metadata

    View full-size slide

  54. Real Values.
    Content Mapping

    View full-size slide

  55. Real Values.
    Using a presentational component
    prototype(Vendor.Site:Content.Teaser) < prototype(Neos.Neos:ContentComponent) {
    renderer = Vendor.Site:Component.Molecule.Teaser {
    title = "Lorem ipsum"
    description = "dolor sit amet"
    imageUrl = "//dummyimage.com/600x400/000/fff"
    link = "http://www.sitegeist.de"
    }
    }

    View full-size slide

  56. Real Values.
    Neos.Neos:ContentComponent =
    Component +
    ContentElementWrapping

    View full-size slide

  57. Real Values.
    Property mapping
    prototype(Vendor.Site:Content.Teaser) < prototype(Neos.Neos:ContentComponent) {
    renderer = Vendor.Site:Component.Molecule.Teaser {
    title = ${q(node).property('title')}
    description = ${q(node).property('description')}
    imageUrl = Neos.Neos:ImageUri {
    asset = ${q(node).property('image')}
    }
    link = ${q(node).property('link')}
    [email protected] = Neos.Neos:ConvertUris
    [email protected] = ${node.context.live}

    View full-size slide

  58. Real Values.
    Editable mapping
    prototype(Vendor.Site:Content.Teaser) < prototype(Neos.Neos:ContentComponent) {
    renderer = Vendor.Site:Component.Molecule.Teaser {
    title = Neos.Neos:Editable {
    property = 'title'
    }
    description = Neos.Neos:Editable {
    property = 'description'
    }
    }
    }

    View full-size slide

  59. Real Values.
    Neos.Neos:Editable =
    BackendTag +
    ContentEditableWrapping

    View full-size slide

  60. Real Values.
    Container Mapping

    View full-size slide

  61. Real Values.
    Collection > Container - 1
    prototype(Vendor.Site:Content.TwoColumn) < prototype(Neos.Neos:ContentComponent)
    renderer = Vendor.Site:Component.Molecule.TwoColumn {
    left = Neos.Neos:PrimaryContent {
    nodePath = 'left'
    }
    right = Neos.Neos:PrimaryContent {
    nodePath = 'right'
    }
    }
    }

    View full-size slide

  62. Real Values.
    Collection > Container 2
    prototype(Vendor.Site:Content.Accordeon) < prototype(Neos.Neos:ContentComponent) {
    renderer = Vendor.Site:Component.Molecule.Accordeon {
    title = Neos.Neos:Editable {
    property = 'title'
    }
    content = Neos.Neos:ContentCollectionRenderer
    }
    }

    View full-size slide

  63. Real Values.
    Collection

    View full-size slide

  64. Real Values.
    Collection > List
    prototype(Vendor.Site:Content.Slider) < prototype(Neos.Neos:ContentComponent) {
    renderer = Vendor.Site:Component.Molecule.Slider {
    slides = Neos.Fusion:RawCollection {
    collection = ${q(node).children('[instanceof Vendor.Site:Content.Slider.Slide]').get
    itemName = 'slide'
    itemRenderer = Neos.Fusion:RawArray {
    title = ${q(slide).property('title')}
    imageUri = Neos.Neos:ImageUri {
    asset = ${q(slide).property('image')}
    }
    }
    }

    View full-size slide

  65. Real Values.
    !!! Editable List
    prototype(Vendor.Site:Content.Slider) < prototype(Neos.Neos:ContentComponent) {
    renderer = Vendor.Site:Component.Molecule.Slider {
    slides = Neos.Fusion:RawCollection {
    itemName = 'slide'
    itemRenderer = Neos.Fusion:RawArray {
    __slideNode = ${slide}
    }
    }
    prototype(Vendor.Site:Component.Molecule.Slide) {
    @process.contentElementWrapping = Neos.Neos:ContentElementWrapping {
    node = ${item.__slideNode}
    }
    }

    View full-size slide

  66. Real Values.
    !!! Editable List
    prototype(Vendor.Site:Content.Slider) < prototype(Neos.Neos:ContentComponent) {
    renderer = Vendor.Site:Component.Molecule.Slider {
    slides = Neos.Fusion:RawCollection {
    itemName = 'slide'
    itemRenderer = Neos.Fusion:RawArray {
    __slideNode = ${slide}
    title = Neos.Neos:Editable {
    property = 'title'
    node = ${slide}
    }
    }
    }

    View full-size slide

  67. Real Values.

    View full-size slide

  68. Real Values.
    Presentation != Integration

    View full-size slide

  69. Real Values.
    #project-atomic-fusion

    View full-size slide

  70. Real Values.
    Thank You!

    View full-size slide

  71. Real Values.
    Questions?

    View full-size slide