Use the function chi.epanel(elem)
to instantiate a new extension panel component in the DOM
element passed as a parameter. It will return an ExpansionPanel object that will provide functions for interacting
with the panel, such as setState
. Valid states are pending
, active
,
disabled
and done
.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. At atque consequatur consequuntur excepturi illo maiores, nobis placeat recusandae rem! Accusantium ad in minus molestiae? Commodi cupiditate labore nihil sed veritatis!
<div class="m-epanel" id="example1">
<div class="m-epanel__header">
<div class="m-epanel__title">Expansion panel</div>
<div class="m-epanel__content">
<div class="m-epanel__collapse">
<div class="-done--only">
<!-- some body content -->
</div>
</div>
</div>
<div class="m-epanel__action -done--only">
<button class="a-btn -primary -flat" data-chi-epanel-action="active">Change</button>
</div>
</div>
<div class="m-epanel__collapse -ml--0">
<div class="-active--only">
<div class="m-epanel__body">
<div class="m-epanel__content">
<div class="m-epanel__subtitle">Active panel title</div>
<!-- some body content -->
</div>
<div class="m-epanel__footer -justify-content--end">
<button class="a-btn -lg">Previous</button>
<button class="a-btn -lg -primary -ml--2">Continue</button>
</div>
</div>
</div>
</div>
</div>
<div class="-d--flex -justify-content--center -mt--3">
<div class="m-form__item -inline -row">
<div class="a-radio">
<input class="a-radio__input" type="radio" name="example1" value="pending" id="example1_radio1" checked="checked">
<label class="a-radio__label" for="example1_radio1">Pending</label>
</div>
</div>
<div class="m-form__item -inline -row">
<div class="a-radio">
<input class="a-radio__input" type="radio" name="example1" value="active" id="example1_radio2">
<label class="a-radio__label" for="example1_radio2">Active</label>
</div>
</div>
<div class="m-form__item -inline -row">
<div class="a-radio">
<input class="a-radio__input" type="radio" name="example1" value="done" id="example1_radio3">
<label class="a-radio__label" for="example1_radio3">Done</label>
</div>
</div>
<div class="m-form__item -inline -row">
<div class="a-radio">
<input class="a-radio__input" type="radio" name="example1" value="disabled" id="example1_radio4">
<label class="a-radio__label" for="example1_radio4">Disabled</label>
</div>
</div>
</div>
var epDom = document.getElementById('example1');
var ePanel = chi.expansionPanel(epDom);
var checkBoxes = document.querySelectorAll('input[name="example1"]');
// Add event listeners to radio buttons
Array.prototype.forEach.call(
checkBoxes,
function(input) {
input.addEventListener('change', function() {
if (this.checked) {
ePanel.setState(this.value);
}
}, false);
}
);
// Listen to Extension Panel state changes and update radio buttons
epDom.addEventListener('chi.epanel.change', function() {
var state = ePanel.getStateName();
Array.prototype.forEach.call(
checkBoxes,
function(input) {
if (input.value === state) {
input.checked = true;
}
}
);
});
You can bind actions to activators inside the expansion panel with the data-chi-epanel-action
attribute.
Action | Description |
---|---|
pending | Sets the panel to the pending state. All the contents under the -active--only and the
-done--only will not be visible. |
active | Sets the panel to the active state. All the contents under the -active--only will be visible. |
toggle | In the case the panel is previously set to active, this action sets it to pending. It sets to active state otherwise. |
done | Sets the panel to the done state. All the contents under the -done--only will be visible. |
disabled | Sets the panel to the disabled state. All the contents under the -active--only and the
-done--only will not be visible, and the title will render in a soft grey color. |
inactive | Is a synonym for pending . |
next | Sets the next panel in active status. |
previous | Sets the previous panel in active status. |
TipYou can freely add, remove or change the data-chi-epanel-action
attribute on the fly, as is the main
element with the m-epanel
class, the one which listens for the events.
Content in expansion panel
<div class="m-epanel" id="example2" data-chi-epanel-group="example2">
<div class="m-epanel__header">
<div class="m-epanel__title" data-chi-epanel-action="toggle">Click me to toggle</div>
<div class="m-epanel__content">
<div class="m-epanel__collapse">
<div class="-done--only">CenturyLink...</div>
</div>
</div>
<div class="m-epanel__action -done--only">
<button class="a-btn -primary -flat" data-chi-epanel-action="active">Change</button>
</div>
</div>
<div class="m-epanel__collapse -ml--0">
<div class="-active--only">
<div class="m-epanel__body">
<div class="m-epanel__content">
<div class="m-epanel__subtitle">Active panel title</div>
<p class="m-epanel__text">Content in expansion panel</p>
</div>
<div class="m-epanel__footer -justify-content--end">
<button class="a-btn -lg" data-chi-epanel-action="pending">Pending</button>
<button class="a-btn -lg -primary -ml--2" data-chi-epanel-action="done">Done</button>
</div>
</div>
</div>
</div>
</div>
var ep = chi.expansionPanel(document.getElementById('example2'));
The real power of the component comes when several expansion panels are used together. You can group them using the
attribute data-chi-epanel-group="name-of-the-group"
. Now they will work together as an stepped form. When
an element is activated, the previous expanding panels will get the done state and the next will get the pending
state.
Content in expansion panel
Content in expansion panel
Content in expansion panel
Content in expansion panel
<div class="m-epanel -active" data-chi-epanel-group="example3">
<div class="m-epanel__header">
<div class="m-epanel__title">Expansion panel #1</div>
<div class="m-epanel__content">
<div class="m-epanel__collapse">
<div class="-done--only">Done<br>CenturyLink...</div>
</div>
</div>
<div class="m-epanel__action -done--only">
<button class="a-btn -primary -flat" data-chi-epanel-action="active">Change</button>
</div>
</div>
<div class="m-epanel__collapse -ml--0">
<div class="-active--only">
<div class="m-epanel__body">
<div class="m-epanel__content">
<div class="m-epanel__subtitle">Active panel title</div>
<p class="m-epanel__text">Content in expansion panel</p>
</div>
<div class="m-epanel__footer -justify-content--end">
<button class="a-btn -lg -primary -ml--2" data-chi-epanel-action="next">Continue</button>
</div>
</div>
</div>
</div>
</div>
<div class="m-epanel" data-chi-epanel-group="example3">
<div class="m-epanel__header">
<div class="m-epanel__title">Expansion panel #2</div>
<div class="m-epanel__content">
<div class="m-epanel__collapse">
<div class="-done--only">Done<br>CenturyLink...</div>
</div>
</div>
<div class="m-epanel__action -done--only">
<button class="a-btn -primary -flat" data-chi-epanel-action="active">Change</button>
</div>
</div>
<div class="m-epanel__collapse -ml--0">
<div class="-active--only">
<div class="m-epanel__body">
<div class="m-epanel__content">
<div class="m-epanel__subtitle">Active panel title</div>
<p class="m-epanel__text">Content in expansion panel</p>
</div>
<div class="m-epanel__footer -justify-content--end">
<button class="a-btn -lg" data-chi-epanel-action="previous">Previous</button>
<button class="a-btn -lg -primary -ml--2" data-chi-epanel-action="next">Continue</button>
</div>
</div>
</div>
</div>
</div>
<!-- last div x3 -->
chi.expansionPanel(document.querySelectorAll('[data-chi-epanel-group="example3"]'));
You can configure the expansion panels component to work as an accordion in a way that when an element is activated,
any other panel in the same group will be deactivated by putting it in the pending state. To activate this mode, you
have to add the mode: "accordion"
configuration parameter at the moment of creation. Done states should
not be used in this mode. In this example, titles have been configured to trigger the action toggle
,
and the expansion panel #3 also have next and previous buttons that fulfills the accordion behavior.
Content in expansion panel
Content in expansion panel
Content in expansion panel
Content in expansion panel
<div class="m-epanel -bordered -active" data-chi-epanel-group="example4">
<div class="m-epanel__header">
<div class="m-epanel__title" data-chi-epanel-action="toggle">Expansion panel #1</div>
</div>
<div class="m-epanel__collapse">
<div class="-active--only">
<div class="m-epanel__body">
<div class="m-epanel__content">
<div class="m-epanel__subtitle">Active panel title</div>
<p class="m-epanel__text">Content in expansion panel</p>
</div>
</div>
</div>
</div>
</div>
<div class="m-epanel -bordered" data-chi-epanel-group="example4">
<div class="m-epanel__header">
<div class="m-epanel__title" data-chi-epanel-action="toggle">Expansion panel #2</div>
</div>
<div class="m-epanel__collapse">
<div class="-active--only">
<div class="m-epanel__body">
<div class="m-epanel__content">
<div class="m-epanel__subtitle">Active panel title</div>
<p class="m-epanel__text">Content in expansion panel</p>
</div>
</div>
</div>
</div>
</div>
<!-- last div x3 -->
chi.expansionPanel(
document.querySelectorAll('[data-chi-epanel-group="example4"]'),
{mode: 'accordion'}
);
In this mode, there is no automated action triggered when an element activates. So you have to manage all custom behavior.
Content in expansion panel
Content in expansion panel
Content in expansion panel
Content in expansion panel
<div class="m-epanel -bordered -active" data-chi-epanel-group="example5">
<div class="m-epanel__header">
<div class="m-epanel__title" data-chi-epanel-action="toggle">Expansion panel #1</div>
</div>
<div class="m-epanel__collapse">
<div class="-active--only">
<div class="m-epanel__body">
<div class="m-epanel__content">
<div class="m-epanel__subtitle">Active panel title</div>
<p class="m-epanel__text">Content in expansion panel</p>
</div>
</div>
</div>
</div>
</div>
<div class="m-epanel -bordered" data-chi-epanel-group="example4">
<div class="m-epanel__header">
<div class="m-epanel__title" data-chi-epanel-action="toggle">Expansion panel #2</div>
</div>
<div class="m-epanel__collapse">
<div class="-active--only">
<div class="m-epanel__body">
<div class="m-epanel__content">
<div class="m-epanel__subtitle">Active panel title</div>
<p class="m-epanel__text">Content in expansion panel</p>
</div>
</div>
</div>
</div>
</div>
<!-- last div x3 -->
chi.expansionPanel(
document.querySelectorAll('[data-chi-epanel-group="example5"]'),
{mode: 'free'}
);
Write your custom mode by adding a handler for state changes of the expansion panels in the configuration, and
writing your own functions for the active
, done
, pending
,
disabled
, toggle
, next
and previous
actions. In the
example, the component behaves similar to the accordion but alternates between done
and
pending
states instead of active
and pending
states. The overridden action
functions are for documenting purposes only because they clone the functionality of the default ones.
<div class="m-epanel -done" data-chi-epanel-group="example6">
<div class="m-epanel__header">
<div class="m-epanel__title" data-chi-epanel-action="done">Expansion panel #1</div>
<div class="m-epanel__content">
<div class="m-epanel__collapse">
<div class="-done--only">CenturyLink...</div>
</div>
</div>
</div>
</div>
<div class="m-epanel" data-chi-epanel-group="example6">
<div class="m-epanel__header">
<div class="m-epanel__title" data-chi-epanel-action="done">Expansion panel #2</div>
<div class="m-epanel__content">
<div class="m-epanel__collapse">
<div class="-done--only">CenturyLink...</div>
</div>
</div>
</div>
</div>
<!-- last div x3 -->
chi.expansionPanel(
document.querySelectorAll('[data-chi-epanel-group="example6"]'),
{
mode: 'custom',
changeHandler: function (newState, oldState, expansionPanel, panelGroup) {
if (newState === chi.EXPANSION_PANEL_STATES.DONE) {
panelGroup.expansion_panels.forEach(function (exPa) {
if (exPa !== expansionPanel) {
exPa.setState(chi.EXPANSION_PANEL_STATES.PENDING.NAME);
}
});
}
},
customActions: {
active: (expansionPanel, epGroup) =>
expansionPanel.setState(chi.EXPANSION_PANEL_STATES.ACTIVE.NAME),
done: (expansionPanel, epGroup) =>
expansionPanel.setState(chi.EXPANSION_PANEL_STATES.DONE.NAME),
pending: (expansionPanel, epGroup) =>
expansionPanel.setState(chi.EXPANSION_PANEL_STATES.PENDING.NAME),
toggle: (expansionPanel, epGroup) => {
if (expansionPanel._state === chi.EXPANSION_PANEL_STATES.ACTIVE) {
expansionPanel.setState(chi.EXPANSION_PANEL_STATES.PENDING.NAME);
} else {
expansionPanel.setState(chi.EXPANSION_PANEL_STATES.ACTIVE.NAME);
}
},
next: (expansionPanel, epGroup) => {
epGroup.reset(expansionPanel);
epGroup.next().setState(chi.EXPANSION_PANEL_STATES.ACTIVE.NAME);
},
previous: (expansionPanel, epGroup) => {
epGroup.reset(expansionPanel);
epGroup.previous().setState(chi.EXPANSION_PANEL_STATES.ACTIVE.NAME);
},
disabled: (expansionPanel, epGroup) =>
expansionPanel.setState(chi.EXPANSION_PANEL_STATES.DISABLED.NAME)
}
}
);
Expansion panel components have a dispose function to free all resources attached to the element, such as event listeners and object data. You should call this method when you want to remove the component.
var elemArray = document.querySelectorAll('[data-chi-epanel-group="groupName"]');
var expansionPanelsArray = chi.expansionPanel(elemArray);
// do stuff
expansionPanelsArray.forEach(function (expansionPanel) {
expansionPanel.dispose();
});
TipIt is safe to call the expansionPanel
method more than once, as it will return any previously created
expansion panel component associated to the element.
var elem = document.getElementById('expansion-panel-1');
var expansionPanelComponent = chi.expansionPanel(elem);
var elem2 = document.getElementById('expansion-panel-1');
var expansionPanelComponent2 = chi.expansionPanel(elem2);
expansionPanelComponent === expansionPanelComponent2; // returns true
expansionPanelComponent.dispose(); // Only have to do it once.