Skip to content

Instantly share code, notes, and snippets.

@elbakerino
Last active June 21, 2022 10:56
Show Gist options
  • Save elbakerino/0c290854e923c7933196243da9227dc7 to your computer and use it in GitHub Desktop.
Save elbakerino/0c290854e923c7933196243da9227dc7 to your computer and use it in GitHub Desktop.
Example JS for the Formanta/Sass tabs component
const calcTabHeight = (tab) => {
// todo: find a better way to get the correct height size of tab + tab content
const tabContentHeight = Array.from(tab.children).reduce((height, child) => {
const styles = window.getComputedStyle(child);
const styleGutter = parseFloat(styles.getPropertyValue('margin-top')) +
parseFloat(styles.getPropertyValue('margin-bottom'));
return height + child.getBoundingClientRect().height + styleGutter;
}, 0);
const styles = window.getComputedStyle(tab);
const styleGutter = parseFloat(styles.getPropertyValue('padding-top')) +
parseFloat(styles.getPropertyValue('padding-bottom'));
const stylesScroller = window.getComputedStyle(tab.parentElement);
const styleGutterScroller = parseFloat(stylesScroller.getPropertyValue('padding-top')) +
parseFloat(stylesScroller.getPropertyValue('padding-bottom')) +
parseFloat(stylesScroller.getPropertyValue('border-top')) +
parseFloat(stylesScroller.getPropertyValue('border-bottom'));
tab.parentElement.style.height = (tabContentHeight + styleGutter + styleGutterScroller) + 'px';
};
const tabContainers = Array.from(document.querySelectorAll('[data-tabs]'));
tabContainers.forEach(tabContainer => {
const tabHeight = tabContainer.dataset.tabsHeight || 'fix';// `fixed` or `flex`
const inactiveClass = tabContainer.dataset.tabsInactiveClass?.split(' ') || [];// any single / multiple css class separated by spaces
const activeClass = tabContainer.dataset.tabsActiveClass?.split(' ') || ['toggle-active'];// any single / multiple css class separated by spaces
const scrollBehaviour = tabContainer.dataset.tabsScrollBehaviour || undefined;// `auto` or `smooth`
const tabToggles = Array.from(tabContainer.querySelectorAll('[data-tabs-toggle]'));
const initialActiveToggle = tabContainer.querySelector('.' + activeClass.join('.') + '[data-tabs-toggle]');
if(!initialActiveToggle) {
console.error('Initial Active Tab Toggle missing for: ', tabContainer);
return;
}
const allTabs = tabContainer.querySelectorAll('[data-tabs-target]');
const initialActiveTab = tabContainer.querySelector('[data-tabs-target="' + initialActiveToggle.dataset.tabsToggle + '"]');
if(!initialActiveTab) {
console.error('Initial Active Tab missing for: ', initialActiveToggle.dataset.tabsToggle, initialActiveToggle);
return;
}
if(tabHeight === 'flex') {
calcTabHeight(initialActiveTab);
}
initialActiveTab.parentElement.scrollTo({
left: initialActiveTab.offsetLeft,
behavior: scrollBehaviour,
});
initialActiveTab.style.visibility = null;
allTabs.forEach(tab => {
if(tab !== initialActiveTab) {
tab.style.visibility = 'hidden';
}
});
tabToggles.forEach(
tabToggle =>
tabToggle.addEventListener('click', (e) => {
const toggle = e.target;
const tabTarget = e.target.dataset.tabsToggle;
const activeTab = tabContainer.querySelector('[data-tabs-target="' + tabTarget + '"]');
if(!activeTab) {
console.error('Tab missing for toggle: ', toggle);
return;
}
activeTab.parentElement.scrollTo({
left: activeTab.offsetLeft,
behavior: scrollBehaviour,
});
activeTab.style.visibility = null;
allTabs.forEach(tab => {
if(tab !== activeTab) {
tab.style.visibility = 'hidden';
}
});
if(tabHeight === 'flex') {
calcTabHeight(activeTab);
}
toggle.parentElement.querySelectorAll('[data-tabs-toggle]')
.forEach((tabToggleInParent) => {
if(tabToggleInParent === toggle) {
activeClass.forEach((c) => tabToggleInParent.classList.add(c));
inactiveClass.forEach((c) => tabToggleInParent.classList.remove(c));
return;
}
activeClass.forEach((c) => tabToggleInParent.classList.remove(c));
inactiveClass.forEach((c) => tabToggleInParent.classList.add(c));
});
})
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment