Tab
import Tab, { parseOptions } from '@bbc/front-end-kit/js/components/Tab';
Provides us with a component that toggles based on one or more triggers. A bit like the Popup component, but used for all other toggleable elements that don't require a dialog DOM element nor requruires Popup specific kind of behaviors. It is just made to hide/show elments accross the page.
It extends from the Component class.
Getting started
To get started the tab component receives at least two parameters: The element and one or more triggers
The minimal HTML structure needed to initialise the tab component
<!-- Tab trigger -->
<button class="tab-trigger">Trigger tab</button>
<div class="tab">
<!-- Tab content -->
</div>
Initialise it with javascript
const $tabElement = document.querySelector('.tab');
const $tabTriggerElement = document.querySelector('.tab-trigger')
const tab = new Tab({
$el: $tabElement,
$trigger: $tabTriggerElement
});
The .tab component is now toggleable by clicking on the .tab-trigger button.
Automatic trigger linking
The tab component will automatically look for triggers in the DOM when the DOM element is provided with a data-tab attribute containing a unique ID. All triggers in the DOM containing a data-tab-trigger attribute with the same ID as value, will be considered triggers for the instance and will be able to toggle the tab instance after initialisation
<!-- Tab trigger -->
<button class="tab-trigger" data-tab-trigger="customTabId">Trigger tab</button>
<div class="tab" data-tab="customTabId">
<!-- Tab content -->
</div>
const $tabElement = document.querySelector('.tab');
const tab = new Tab({
$el: $tabElement,
});
Grouping of tabs
Tabs can be grouped in memory. By grouping the tabs, it will ensure all other tabs are closed or will close when a new tab of the group is triggered to open.
To achieve this, a group name needs to be provided for the group property of the constructor object.
// tab1 and tab2 will not be opened together
const tab1 = new Tab({
$el: $tabElement1,
$trigger: $tabTriggerElement1,
group: 'myCustomGroup'
});
const tab2 = new Tab({
$el: $tabElement2,
$trigger: $tabTriggerElement2,
group: 'myCustomGroup'
});
Animations
The Tab component allows the build-in animations to be overridden during initialization. The custom show/hide methods can be passed using the animation object as a parameter of the c
Override the animations
Simply during initialisation:
const Tab = new Tab({
animations: {
show: myCustomShowAnimation,
hide: myCustomHideAnimation
}
})
Although it is advised to extend from Tab first and override the args object of the constructor before it is passed to the Tab constructor
class CustomTab extends Tab {
constructor (args = {}) {
// override args parameters
args.animations = args.animations || {};
args.animations.show = myCustomShowAnimation;
args.animations.hide = myCustomHideAnimation;
// run super constructor
super(args);
}
}
Animation method requirements
Custom animation methods require to return a Promise that resolves when the animation is completes. This lets the Tab know when the animation is complete so that the logic that is waiting can continue.
The method will be called using the instance as scope (this) and receives the options as parameter comming from the show/hide/toggle methods
function myCustomShowAnimation (options = {}) {
return new Promise(resolve => {
// the custom animation using gsap in this case
gsap.to(this.$el, {
opacity: 1,
onComplete: resolve
})
///
})
}
API
Methods
constructor(args = {})
The constructor method initialises the new Tab instance.
Parameters
args: The configuration object used by the constructor to initialise the Tab in the desired way.$triggers: List of DOM elements that will be used to toggle the state of the Tab (DOM element or list of DOM elements)isOpen(Boolean, defaultfalse): Sets the initial open state. Iffalse, the element is hidden instantly and silently during construction.group(String, defaultnull): Group name. Tabs sharing a group name will close each other when one opens.hash(String, defaultnull): Stored as_hashbut not currently read after assignment — intended as a future feature for URL-hash-based auto-open. Do not rely on this.animations: Object that allows the built-in show/hide animations to be overridden with different methodsshow: Method that will be used to show the Tabhide: Method that will be used to hide the Tab
- ... Component properties
show (options)
Show the Tab using either a built-in animation or a custom animation defined during initilisation
Parameters
options: Object with extra customisations during runtime that will be applied while the show state is triggeredinstant: skips the animation if true (default: false)
Tips
If true is passed instead of an options object, it will be interpreted as a value for the instant property of the options object. The animation will be skipped
Return
Returns a Promise that resolves when the transition is done.
hide (options)
Hide the Tab using either a built-in animation or a custom animation defined during initilisation
Parameters
options: Object with extra customisations during runtime that will be applied while the hide state is triggeredinstant: skips the animation if true (default: false)
Tips
If true is passed instead of an options object, it will be interpreted as a value for the instant property of the options object. The animation will be skipped
Return
Returns a Promise that resolves when the transition is done.
toggle (options)
Toggles the Tab depending on it's current state using either a built-in animation or a custom animation defined during initilisation. It will use the corresponding show/hide method behind the scenes.
Parameters
options: Object with extra customisations during runtime that will be applied while the hide state is triggeredinstant: skips the animation if true (default: false)show(Boolean, optional): Force show (true) or hide (false) instead of toggling.
Tips
If true is passed instead of an options object, it will be interpreted as a value for the instant property of the options object. The animation will be skipped
Return
Returns undefined. Use show() or hide() directly if you need to await the animation Promise.
addTrigger (...triggers)
Registers one or more DOM elements as triggers to toggle the Tab on click.
Parameters
...triggers: The DOM element to register. Every parameter passed will be registered as trigger. Parmeters may also be arrays of triggers.
Return
Return undefined
// single element
tab.addTrigger($trigger)
// multiple elements over parameters
tab.addTrigger($trigger1, $trigger2, $trigger3)
// array of triggers
tab.addTrigger([$trigger1, $trigger2, $trigger3])
// combination of both
tab.addTrigger($trigger1, [$trigger2, $trigger3], $trigger4)
destroy ()
Forces the tab open via show(true) and then calls super.destroy(). This ensures the element is visible before the instance is torn down.
Exported methods
parseOptions (options = {})
Normalises the options argument passed to show/hide/toggle. If a non-object is passed, it is treated as the instant boolean: parseOptions(true) → { instant: true }. Used internally but exported for subclasses or custom animation functions that need the same normalisation.
Getters & Setters
isOpen
Returns the current open state of the Tab.
true: open/visiblefalse: closed/hidden
isTransitioning
Returns the state of the animation it is currently performing
true: transitioning/animatingfalse: idle (not animating)
$triggers
Returns the list of triggers that are registered to toggle the popup on click.
Events
Tab dispatches events using the EventDispatcher's api since Component extends from EventDispatcher
before-show
Fired before the show animation starts. isOpen is already true at this point.
after-show
Fired after the show animation completes. isTransitioning is back to false.
before-hide
Fired before the hide animation starts. isOpen is already false at this point.
after-hide
Fired after the hide animation completes. isTransitioning is back to false.
trigger-click
Fired when a registered trigger is clicked, before toggle() is called. Access via e.detail — note: the source passes originalEvent directly on the event options object, not nested under detail:
e.detail.originalEvent: The originalclickevent.
Private properties
_$triggers
Array of linked triggers that are able to toggle the instance
_hash
Hash in the url it will listen to on page load, if present it will be open on page load
_isOpen
The current state of the instance (open or closed)
_group
Group id the instance belongs to. If part of a group, it will make sure others of the group are closed when the instance is opened
_isTransitioning
Boolean to track if the instance is busy performing the animation
_animations
The collection of animations it will use to perform its state changes
External dependencies
- GSAP: Greensock's animation library for the built-in animations
- lodash: For some quick and usefull utility methods like:
flattenDeep: Flattens multi-level arrays
Todo
- Add removeTrigger(...triggers) method
- Create a toggleble class that will provide the toggle logic for both Tab and
Popup