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. Martin Ficzel • Backend Developer • [email protected]

    twitter/slack: @kopfaufholz • Neos Team-Member Atomic-Fusion, AFX • Sitegeist.Monocle • 2 Kids, Climber
  2. Real Values. AFX renderer = afx` <div> <h1 class="headline">{props.title}</h1> <h2

    class="subheadline" @if.has={props.subtitle}>{props.subtitle}</h2> <Vendor.Site:Image uri={props.imageUri} /> </div> `
  3. 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 {
  4. 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
  5. Real Values. • Separation of Presentation and Integration • Isolation

    of all visual aspects in presentational components Principles for structuring projects
  6. Real Values. Presentational Component prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Component) { title =

    '' description = '' renderer = afx` <div class="component"> <h1>{props.title}</h1> <p>{props.description}</p> </div> `
  7. 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.
  8. Real Values. Composition prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Component) { title = ''

    description = '' imageUri = null renderer = afx` <div class="component"> <Vendor.Site:Component.Image src={props.imageUri} alt={props.title} /> <h1>{props.title}</h1> <p>{props.description}</p>
  9. Real Values. Flags prototype(Vendor.Site:Component.Atom.Headline) < prototype(Neos.Fusion:Component) { title = null

    isSpecial = false renderer = afx` <h1 class={'headline' + (props.isSpecial && ' headline--bold')} >{props.title}</h1> ` }
  10. Real Values. Modifier prototype(Vendor.Site:Component.Atom.Headline) < prototype(Neos.Fusion:Component) { title = null

    modifier = null renderer = afx` <h1 class={'headline' + (props.modifier && (' headline--' + modifier))} >{props.title} ` @propTypes { modifier = ${PropTypes.oneOf('bold', 'italic')} } }
  11. Real Values. Augmentation prototype(Vendor.Site:Component.Molecule.TeaserList) < prototype(Neos.Fusion:Componen renderer = afx` <div

    class="teaserlist" data-filter="true"> <Neos.Fusion:Augmenter data-filter-region={teaser.region} data-filter-category={teaser.category} class=”teaserlist__item” > <Vendor.Site:Component.Molecule.Teaser title={teaser.title} description={ /> </Neos.Fusion:Augmenter> ... iv>
  12. Real Values. Conditional Tagname prototype(Vendor.Site:Component.Atom.Button) < prototype(Neos.Fusion:Component) { link =

    null title = null renderer = afx` <Neos.Fusion:Tag tagName={props.link ? 'a' : 'span'} href={props.link} attributes.class="button" > {props.title} </Neos.Fusion:Tag>
  13. Real Values. Optional Section prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Compone title = ''

    subtitle = '' renderer = afx` <div class="component"> <h1>{props.title}</h1> <h2 @if.hasSubtitle={props.subtitle} > {props.subtitle} </h2> </div> ` }
  14. Real Values. Collection prototype(Vendor.Site:Component.Molecule.Slider) < prototype(Neos.Fusion:Component) { // [ {title:

    'lorem', href: 'http://dummyimage.com' }, ... ] items = null renderer = afx` <div class="slider" > <Neos.Fusion:Collection collection={props.items} itemName="item" @children="itemRenderer" > <Vendor.Site:Component.Molecule.Slider.Slide> <Vendor.Site:Component.Image src={item.href} title={item.title}/> /Vendor.Site:Component.Molecule.Slider.Slide>
  15. Real Values. Container prototype(Vendor.Site:Component.Molecule.Accordeon) < prototype(Neos.Fusion:Compone title = '' content

    = '' renderer = afx` <div class="accordeon"> <div class="accordeon__header">{props.title}</div> <div class="accordeon__content">{props.content}</div> </div> ` }
  16. Real Values. Container - content prototype(Vendor.Site:Component.Example) < prototype(Neos.Fusion:Component) { renderer

    = afx` <Vendor.Site:Component.Molecule.Accordeon title=”Headline” > Lorem ipsum </Vendor.Site:Component.Molecule.Accordeon> ` }
  17. 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
  18. 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
  19. 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
  20. 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
  21. 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!
  22. 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
  23. 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
  24. Real Values. Secret 1: NodeType >> Fusion Prototype type =

    ${q(node).property('_nodeType.name')}
  25. Real Values. Secret 2: PrototypeGenerator # # Disable automagic fusion

    prototypes # Vendor.Site:Content.Example: options: fusion: prototypeGenerator: ~
  26. Real Values. <!-- Collection/Content: ContentElementWrapping --> <div data-__neos-node-contextpath="/sites/sitegeistde/main/node-j3xwsoeihfthx@ data-__neos-fusion-path="page<Vendor.Site:Base>/body<Neos.Fusion:Array >

    <h1> <!-- Editable: ContentEditableWrapping --> <span data-__neos-property="title" data-__neos-editable-node-contextpath="/sites/sitegeistde/main/no > Lorem ipsum dolor sit amet </span> Neos Secret 3: Backend Metadata
  27. 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" } }
  28. 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}
  29. 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' } } }
  30. 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' } } }
  31. 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 } }
  32. 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')} } } }
  33. 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} } }
  34. 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} } } }