2017 © Pedro Peláez
 

neos-package atomicfusion-cssmodules

CSS Modules for Atomic.Fusion

image

packagefactory/atomicfusion-cssmodules

CSS Modules for Atomic.Fusion

  • Wednesday, May 16, 2018
  • by grebaldi
  • Repository
  • 1 Watchers
  • 3 Stars
  • 575 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 3 Versions
  • 404 % Grown

The README.md

PackageFactory.AtomicFusion.CssModules

CSS Modules for Atomic.Fusion, (*1)

Why?

Atomic.Fusion enables you to implement a frontend component architecture in Neos.Fusion. In similar environments (like React or Vue.js), CSS Modules have been proven to be a robust solution to avoid CSS global namespace issues and to make your styles portable alongside your components., (*2)

To enable this technology felt like a natural extension to the ecosystem of Atomic.Fusion., (*3)

What do CSS modules do?

In short: CSS Modules convert your CSS class names and other global identifiers (like @keyframes) into unique identifiers. When processing your CSS files, a JSON file is created, that maps the original class name to the new unique one., (*4)

This way it is ensured, that you can always use speaking identifiers that make sense in the context of your component, without having to worry about potential global naming conflicts., (*5)

PackageFactory.AtomicFusion.CssModules helps you to include those *.json files at the right place. It expects them to be present alongisde your Fusion components already - it won't generate them., (*6)

In order to generate CSS Module files, you have to configure your frontend build pipeline accordingly. An example of how this could look like is given in the next section., (*7)

Setting up CSS modules

The following describes an example setup for postcss and postcss-modules. This is not the only way to create such a setup. For further information on this, I suggest you have a look at the postcss-cli and postcss-modules repositories., (*8)

CSS modules require Node JS and two essential dependencies. Make sure, Node JS is available to your set up and that you have a valid package.json file at the root of your repository (or whereever you prefer it to reside)., (*9)

Then install the following packages:, (*10)

yarn add --dev postcss postcss-modules

This example also uses postcss-cli:, (*11)

yarn add --dev postcss-cli

Then create a postcss.config.js in the same directory as your package.json:, (*12)

module.exports = {
    plugins: [
        require('postcss-modules')
    ]
}

Create a Makefile containing a recipe for building your CSS in the same directory as your package.json:, (*13)

SHELL=/bin/bash
export PATH := $(PATH):./node_modules/.bin
export SITE_PACKGE_DIR="./Packages/Sites/Vendor.Site"

build-css:
    # Build CSS with postcss
    postcss \
        ${SITE_PACKGE_DIR}/Resources/Private/Fusion/**/*.css \
        --dir ${SITE_PACKGE_DIR}/Resources/Public/Styles/temp
    # Concat all built CSS files
    cat ${SITE_PACKGE_DIR}/Resources/Public/Styles/temp/* > ${SITE_PACKGE_DIR}/Resources/Public/Styles/main.css
    # Remove temporary CSS files
    rm -rf ${SITE_PACKGE_DIR}/Resources/Public/Styles/temp

When you run make build-css, all *.css files you have placed alongside your *.fusion component files will afterwards be accompanied by a corresponding *.css.json file containing the map mentioned above., (*14)

Usage in Fusion

Consider the following css file (let's say Vendor.Site/Resources/Private/Fusion/MyComponent/MyComponent.css):, (*15)

.myComponent {
    display: block;
}

.isActive {
    background-color: blue;
}

After running make build-css, a file Vendor.Site/Resources/Private/Fusion/MyComponent/MyComponent.css.json should appear., (*16)

In your Vendor.Site/Resources/Private/Fusion/MyComponent/MyComponent.fusion file, you can now access the class names like this:, (*17)

prototype(Vendor.Site:MyAwesomeComponent) < prototype(PackageFactory.AtomicFusion:Component) {
    # Fusion
    renderer = Neos.Fusion:Tag {
        attributes.class = ${AtomicFusion.classNames(styles.myComponent, props.isActive && styles.isActive)}
    }

    # AFX
    renderer = afx`
        <div
            class={AtomicFusion.classNames(
                styles.myComponent,
                props.isActive && styles.isActive
            )}
            >
        </div>
    `
}

Notice that within your components renderer path, you can now access a special styles context, that contains the class name map., (*18)

Side note: AtomicFusion.classNames is a helper method to concatenate class names conditionally. More on this can found in the Atomic.Fusion main repository., (*19)

Discovery of CSS module files

Fusion actually holds no information about the file a prototype is defined in. So, to enable the discovery of files put alongside those component *.fusion files, we need to configure a lookup pattern:, (*20)

PackageFactory:
  AtomicFusion:
    CssModules:
      tryFiles:
        - resource://{packageKey}/Private/Fusion/{componentPath}.css.json

With the above configuration the CSS module file for the prototype prototype(Vendor.Site:MyAwesomeComponent) will be assumed as resource://Vendor.Site/Private/Fusion/MyAwesomeComponent.css.json., (*21)

{packageKey} and {componentPath} are variables that will be replaced with runtime information of the respective fusion prototype., (*22)

The following variables are considered:, (*23)

  • {prototypeName} - The entire prototype name
  • {packageKey} - The part of the prototype name before the :
  • {componentName} - The part of the prototype name after the :
  • {componentBaseName} - The last part of the componentName, if seperated by dots (for Vendor.Site:Atom.Button that would be: Button)
  • {componentPath} - Similar to {componentName} with all dots being replaced by Directory Separators.

By default, the package looks at the following patterns:, (*24)

resource://{packageKey}/Private/Fusion/{componentPath}.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/{componentBaseName}.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/style.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/Style.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/styles.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/Styles.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/index.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/Index.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/component.css.json
resource://{packageKey}/Private/Fusion/{componentPath}/Component.css.json

Caveats

Recently, the native component prototype Neos.Fusion:Component has arrived in the Neos.Fusion core. Unfortunately, this package won't work with this new prototype and relies on PackageFactory.AtomicFusion:Component to be present., (*25)

This will likely change in the future, either through this package or a PR to Neos.Fusion., (*26)

If you still want to use this package with an existing code base, that relies on Neos.Fusion:Component, you could replace the Neos.Fusion:Component standard implementation with the one for PackageFactory.AtomicFusion:Component:, (*27)

prototype(Neos.Fusion:Component) {
    @class = 'PackageFactory\\AtomicFusion\\FusionObjects\\ComponentImplementation'
}

PackageFactory.AtomicFusion:Component is fully compatible to Neos.Fusion:Component, but you should be nonetheless aware:, (*28)

THIS IS NOT THE JEDI WAY!, (*29)

License

see LICENSE.md, (*30)

The Versions

16/05 2018

dev-master

9999999-dev

CSS Modules for Atomic.Fusion

  Sources   Download

GPL-3.0

The Requires

 

16/05 2018

v2.0.0

2.0.0.0

CSS Modules for Atomic.Fusion

  Sources   Download

GPL-3.0

The Requires

 

24/01 2018

v1.0.0

1.0.0.0

CSS Modules for Atomic.Fusion

  Sources   Download

GPL-3.0

The Requires