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 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 Slide

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

    View Slide

  4. Real Values.
    Terms

    View Slide

  5. Real Values.
    AFX

    View Slide

  6. Real Values.
    AFX
    renderer = afx`

    {props.title}
    {props.subtitle}


    `

    View 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 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 Slide

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

    View Slide

  10. Real Values.
    Atomic.Fusion

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  14. Real Values.
    Patterns for Presentation

    View Slide

  15. Real Values.
    Presentational Component

    View Slide

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

    {props.title}
    {props.description}

    `

    View 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 Slide

  18. Real Values.
    Composition

    View 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 Slide

  20. Real Values.
    Flag

    View Slide

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

    View Slide

  22. Real Values.
    Modifier

    View 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 Slide

  24. Real Values.
    Augment

    View 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 Slide

  26. Real Values.
    Conditional Tagname

    View 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 Slide

  28. Real Values.
    Optional Section

    View Slide

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

    {props.title}

    {props.subtitle}


    `
    }

    View Slide

  30. Real Values.
    Collection

    View 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 Slide

  32. Real Values.
    Container

    View Slide

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

    {props.title}
    {props.content}

    `
    }

    View Slide

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

    Lorem ipsum

    `
    }

    View Slide

  35. Real Values.

    View Slide

  36. Real Values.
    Component APIs

    View 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 Slide

  38. Real Values.
    WWJD?

    View Slide

  39. Real Values.
    What Would JSON Do

    View Slide

  40. Real Values.
    Additional Tools
    for Presentation

    View 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 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 Slide

  43. Real Values.
    Structuring the
    namespace

    View 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 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 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 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 Slide

  48. Real Values.

    View Slide

  49. Real Values.
    Patterns for Integration

    View Slide

  50. Real Values.
    Hidden secrets of Neos

    View Slide

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

    View Slide

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

    View Slide

  53. Real Values.

    data-__neos-node-contextpath="/sites/sitegeistde/main/[email protected]
    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 Slide

  54. Real Values.
    Content Mapping

    View 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 Slide

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

    View 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 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 Slide

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

    View Slide

  60. Real Values.
    Container Mapping

    View 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 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 Slide

  63. Real Values.
    Collection

    View 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 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 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 Slide

  67. Real Values.

    View Slide

  68. Real Values.
    Presentation != Integration

    View Slide

  69. Real Values.
    #project-atomic-fusion

    View Slide

  70. Real Values.
    Thank You!

    View Slide

  71. Real Values.
    Questions?

    View Slide