Style Synergy modules/BEM DOM elements using JavaScript
- Overview
- Installation & Setup
- Synergy Modules/Components
- polymorph()
- API
- Use With sQuery
- Use With Lucid
Polymorph is used for styling DOM elements that follow the Synergy naming convention.
<div class="accordion">
<div class="accordion_panel">
<div class="accordion_title">foo</div>
<div class="accordion_content">bar</div>
</div>
<div class="accordion_panel-active">
<div class="accordion_title">fizz</div>
<div class="accordion_content">buzz</div>
</div>
</div>
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
'position': 'relative'
});
});
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
panel: {
'display': 'block'
}
});
});
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
panel: {
'color': 'white',
'modifier(active)': {
'color': 'blue'
}
}
}
});
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
panel: panel => ({
'color': panel.matches('.accordion_panel-active') ? 'blue' : 'white'
})
}
});
This ensures no class names are hard coded
Learn more about the
modifier
method
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
panel: panel => ({
'color': polymorph.modifier(panel, 'active') ? 'blue' : 'white'
})
}
});
sQuery('accordion', element => {
polymorph(element, {
panel: panel => ({
'color': panel.modifier('active') ? 'blue' : 'white'
})
}
});
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
panel: {
'modifier(active)': {
title: {
'color': 'red'
}
}
},
title: {
'color': 'blue'
}
}
});
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
title: title => ({
'color': title.closest('.accordion_panel-active') ? 'red' : 'blue'
})
}
});
sQuery('accordion', element => {
polymorph(element, {
title: title => ({
'color': title.parent('panel').is('active') ? 'red' : 'blue'
})
}
});
npm install --save @onenexus/polymorph
import 'polymorph' from '@onenexus/polymorph';
polymorph(document.getElementById('someElement'), someConfigurationObject);
Using BEM? Checkout the Working With BEM page
Determine if an HTML element has the specified modifier
polymorph.modifier(element, modifier)
Param | Type | Info |
---|---|---|
element |
HTMLElement |
The HTML element of interest |
modifier |
String |
The modifier of interest |
<div class="accordion">
<div class="accordion_panel">
<div class="accordion_title">foo</div>
<div class="accordion_content">bar</div>
</div>
<div class="accordion_panel-active">
<div class="accordion_title">fizz</div>
<div class="accordion_content">buzz</div>
</div>
</div>
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
panel: panel => ({
'color': polymorph.modifier(panel, 'active') ? 'blue' : 'white'
})
}
});
<div class="accordion">
<div class="accordion_panel" style="color: white;">
...
</div>
<div class="accordion_panel-active" style="color: blue;">
...
</div>
</div>
Repaint the module by re-applying the style rules
element.repaint()
This method is attached directly to the DOM element after the initial
polymorph
call
This is useful for updating the styles after an event that modifies the DOM, such as a click event which adds an active
modifier to an element. In order to repaint the element, you should call the repaint()
method in the same place you handle the event.
<div class="accordion" id="alpha">
<div class="accordion_panel">
<div class="accordion_title">foo</div>
<div class="accordion_content">bar</div>
</div>
<div class="accordion_panel">
<div class="accordion_title">fizz</div>
<div class="accordion_content">buzz</div>
</div>
</div>
polymorph(document.getElementById('alpha'), {
panel: {
'background': 'red';
'modifier(active)': {
'background': 'blue'
}
}
});
// `#alpha` element and all targeted child components
// will now have a `repaint()` method
document.querySelectorAll('.accordion').forEach(accordion => {
accordion.querySelectorAll('.accordion_panel').forEach(panel => {
panel.querySelector('.accordion_title').addEventListener('click', () => {
// do event handling...
panel.classList.toggle('accordion_panel-active');
// repaint the accordion panel
panel.repaint();
});
}
});
Using sQuery
sQuery('accordion').getComponents('panel').forEach(PANEL => {
sQuery(PANEL).getComponent('title').addEventListener('click', () => {
// the `repaint` method is called automatically
// when using the sQuery API
sQuery(PANEL).toggleModifier('visible');
});
});
Using Lucid
// By passing a styles function/object to the `styles` prop of `<Module>`,
// `repaint()` will be called on the approprate rendered DOM elements
// in the `componentDidUpdate` lifecycle method
<Module name='myModule' styles={styles}>...</Module>
sQuery is a JavaScript library for interacting with Synergy modules
sQuery is perfect for interacting with Polymorph
, and isn't included by default to keep bundle size down (as it isn't strictly required for functionality).
Once installed, you can use sQuery to style your modules and components much more easily using the provided API.
document.querySelectorAll('.accordion').forEach(element => {
polymorph(element, {
title: title => ({
'color': title.closest('.accordion_panel-active') ? 'red' : 'blue'
})
}
});
sQuery('accordion', element => polymorph(element, {
title: title => ({
'color': title.parent('panel').is('active') ? 'red' : 'blue'
})
}));
Lucid is a set of higher-order React components for rendering Synergy modules
Lucid and Polymorph were built in tandem as part of the Synergy
framework, so go hand-in-hand together. If you are using Lucid, the easiest way to use Polymorph as the styleParser
function is to attach it to the window.Synergy.styleParser
property:
import { Module, Component } from '@onenexus/lucid';
import Polymorph from '@onenexus/polymorph';
window.Synergy = {
styleParser: Polymorph
}
// start using Lucid components (Module, Component)...