Sitegeist.Monocle
An fusion based styleguide implementation for Neos
Install / Use
/learn @sitegeist/Sitegeist.MonocleREADME
Sitegeist.Monocle
<img src="./Resources/Public/Images/monocle_imagemark.svg" width="300" />A living styleguide for Neos
This package adds a styleguide module to Neos that renders the
Fusion prototypes in isolation that are annotated with @styleguide.
Authors & Sponsors
- Martin Ficzel - ficzel@sitegeist.de
- Wilhelm Behncke - behncke@sitegeist.de
The development and the public-releases of this package is generously sponsored by our employer http://www.sitegeist.de.
Living Styleguide
The Monocle-Module uses the real Fusion-code to render the annotated prototypes in isolation. That way the styleguide is always up to date and cannot diverge over time from the real codebase.
The Monocle was defined with Atomic-Design and pure Fusion without Fluid in mind but the implementation is Coding-Style and Template-Engine agnostic. You can use Monocle to render Fluid based Prototypes without any limitation.
Installation
Sitegeist.Monocle is available via packagist and can be installed with the command composer require sitegeist/monocle.
We use semantic-versioning so every breaking change will increase the major-version number.
Usage
Create items for the styleguide
To render a prototype as a styleguide-item it simply has to be annotated:
prototype(Vendor.Package:Components.Headline) < prototype(Neos.Fusion:Component) {
#
# styleguide annotation to define title, description and props for the styleguide
#
@styleguide {
title = 'My Custom Prototype'
description = 'A Prototype ....'
props {
content = 'Hello World'
}
useCases {
h2 {
title = "My Custom Prototype as Headline 2"
props {
tagName = 'h2'
content = 'Alternate styleguide content for h2'
}
}
}
}
#
# normal fusion props and renderer
#
tagName = 'h1'
content = ''
renderer = afx`
<Neos.Fusion:Tag tagName={props.tagName}>{props.content}</Neos.Fusion:Tag>
`
}
The styleguide will render the items without the usual context. The site, documenNode
and node context variables are not present inside the styleguide rendering by intention.
That way it is ensured that your prototypes rely only on the fusion path for rendering and are not affected by editor data. This is important for reliable testing of components.
To map an actual content-node on a component-prototype use a separate fusion prototype.
prototype(Vendor.Package:Content.Headline) < prototype(Neos.Neos:ContentComponent){
content = ${q(node).property('title')}
renderer = Vendor.Package:Components.Headline {
@apply.props = ${props}
}
}
That way the rendering prototype is completely separated from the mapping prototype and therefore highly reusable.
The distinction between rendering- and mapping-prototypes can be compared to presentational-components vs. container-components in the ReactJS world.
Preview Containers
Often components have to be rendered in the styleguide inside another component. In this case a container
can be defined in the styleguide annotation. The container is applied as a processor to the currently previewed
prototype with the rendered content available as value in the context.
prototype(Vendor.Site:ExampleComponent) < prototype(Neos.Fusion:Component) {
@styleguide {
container = Vendor.Site:ExampleContainer {
content = ${value}
}
}
renderer = afx`
<h1>Hello World</h1>
`
}
For flexibility it is advisible to define a prop content = ${value} on container prototyoes which ensures
that the containers can be used as processor or via afx with tag children.
prototype(Vendor.Site:ExampleContainer) < prototype(Neos.Fusion:Component) {
content = ${value}
renderer = afx`
<div class="container">{props.content}</div>
`
}
# Use of container as processor ... content passed via `value` context
example_processor = 'Hello World'
example_processor.@process.inContainer = Vendor.Site:ExampleContainer
# Use of container in afx ... content passed as `content`-prp
example_afx = afx`
<Vendor.Site:ExampleContainer>Hello World'</Vendor.Site:ExampleContainer>
`
When multiple styleguide elements are nested please note that only the container for the outermost element will be rendered. For all nested elements
the container will be omitted. This also applies to prototypes rendered by Sitegeist.Monocle:Preview.Prototype.
Use Cases
The useCases section of the styleguide annotation allows to configure scenarios the component shall be previewed in.
If a useCase defines props or container those are will override the styleguide settings for this component. The title
is optional and will fallback to the key the useCase is defined in.
prototype(Vendor.Site:Example.Component) < prototype(Neos.Fusion:Component) {
@styleguide {
title = "Example"
container = Vendor.Site:Example.Container
props {
title = 'Hello world!'
}
useCases {
case1 {
title = "Use case with varying props"
props {
title = Hello special world!'
}
}
case2 {
title = "Use case with another container"
container = Vendor.Site:Example.AnotherContainer
}
}
Prop Sets !!!deprecated!!!
!!! PropSets are deprecated and should not be mixed with UseCases. Monocle will not show the PropSet selector for components that have useCases and the API endpoint will ignore propSets once a useCase is selected. The PropSet Feature will be removed in one of the next major versions once if causes extra effort to the monocle maintenance !!!
PropSets allow to specify additional values for props that are merged into the main styleguide props of a component to allow to simulate wider range of scenarios a component may be used.
prototype(Vendor.Site:Example.Component) < prototype(Neos.Fusion:Component) {
@styleguide {
title = "Example"
props {
title = 'Hello world!'
}
propSets {
longTitle {
title = 'A very long title for testing ... because reasons'
}
}
}
}
Preview Configuration
Some configuration is available to configure the preview.
Sitegeist:
Monocle:
preview:
#
# The fusion path that renders the preview.
# the available context is has the values
# - sitePackageKey
# - prototypeName
# - propSet
# - props
#
fusionRootPath: '/<Sitegeist.Monocle:Preview.Page>'
#
# The fusion prototype that is rendered initially
# Optional: Will default to the first found prototype
#
defaultPrototypeName: 'Vendor.Site:Prototype'
#
# The query selector that is used to extract the component html
# from the preview to the html-view.
# Optional: Default is 'body'
#
sourceQuerySelector: 'body'
To include your styles and scripts into the preview you can extend the Sitegeist.Monocle:Preview.Page prototype the
same way you would customize Neos.Neos:Page.
//
// Add stylesheets to to the preview-prototype
//
prototype(Sitegeist.Monocle:Preview.Page) {
head {
stylesheets.main = Vendor.Site:Resources.Styles
javascripts.main = Vendor.Site:Resources.Scripts
}
bodyScripts = Vendor.Site:Resources.BodyScripts {
@position = 'before closingBodyTag'
}
}
Grids
The key grids in the monocle ui configuration allows to specify a responsive layout grid visualization
that can be activated in the monocle ui or the preview endpoint.
Each grid has the following options:
-
mediaQuery(string, required) media query the grid shall be active for -
columns(int, required) number of columns -
gap(string, required) gap between columns, css units like "10px" -
gutter(string, required) border around of the grid, css dimensions like for padding "0px 20px" -
label(string, optional) name of the grid configuration -
width(string, default: 100%) css with of the grid. default -
maxWidth(string, optional) css max-with of the grid -
margin(string, default: "0px auto") css margin around the grid
!!! The grid visualization assumes that the body of the document has no padding or margin. If this is not the case the grid may not be positioned or dimensioned correctly !!!
Sitegeist:
Monocle:
ui:
grids:
small:
mediaQuery: '(min-width:0px) and (max-width: 599px)'
label: "Small"
columns: 4
gap: 16px
gutter: 10px 20px
medium:
mediaQuery: '(min-width:600px) and (max-width: 1023px)'
label: Medium
columns: 8
gap: 16px
gutter: 10px 20px
large:
mediaQuery: '(min-width:1024px)'
label: Large
columns: 12
maxWidth: 1024px
gap: 16px
gutter: 10px 20px
Viewports
To configure the available viewport presets you can alter the following configuration.
Sitegeist:
Monocle:
ui:
viewportPresets:
xs:
label: 'xtra small'
width: 400
height: 600
md:
label: 'medium'
width: 600
height: 400
l:
label: 'wide'
width: 800
height: 600
Locales
If you have translations in your component you can configure the available locales via settings
Sitegeist:
Monocle:
ui:
localePresets:
