Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stepped class in wizard/tabs #1489

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@
static cssClasses = {
button: {
disabled: "cmp-accordion__button--disabled",
expanded: "cmp-accordion__button--expanded"
expanded: "cmp-accordion__button--expanded",
stepped: "cmp-accordion__button--stepped"
},
panel: {
hidden: "cmp-accordion__panel--hidden",
expanded: "cmp-accordion__panel--expanded"
expanded: "cmp-accordion__panel--expanded",
stepped: "cmp-accordion__panel--stepped"
}
};

Expand Down Expand Up @@ -239,6 +241,11 @@
item.removeAttribute(this.constructor.dataAttributes.item.expanded);
var button = this.getCachedButtons()[index];
var panel = this.getCachedPanels()[index];
if (button.classList.contains(this.constructor.cssClasses.button.expanded)) {
// Only apply `stepped` class if the tab was previously expanded
button.classList.add(this.constructor.cssClasses.button.stepped);
panel.classList.add(this.constructor.cssClasses.panel.stepped);
}
button.classList.remove(this.constructor.cssClasses.button.expanded);
// used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute
// e.g. https://bugs.webkit.org/show_bug.cgi?id=210934
Expand All @@ -250,8 +257,9 @@
panel.setAttribute("aria-hidden", true);
}
}
}
};
}


window.Forms = window.Forms || {};
window.Forms.CoreComponentsCommons = window.Forms.CoreComponentsCommons || {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@
}
this.expandItem(itemDivToExpand);
this.collapseAllOtherItems(itemDivToExpand.id);

const cachedItems = this.getCachedItems();
const newIndex = cachedItems.indexOf(itemDivToExpand);
this.getCachedButtons()[newIndex].classList.remove(this.constructor.cssClasses.button.stepped);
this.getCachedPanels()[newIndex].classList.remove(this.constructor.cssClasses.panel.stepped);

this.#showHideRepeatableButtons(childView.getInstanceManager());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ BLOCK cmp-tabs
ELEMENT cmp-tabs__tablist
ELEMENT cmp-tabs__tab
MOD cmp-tabs__tab--active
MOD cmp-tabs__tab--stepped
ELEMENT cmp-tabs__title
ELEMENT cmp-tabs__icon
ELEMENT cmp-tabs__label
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
tab: "cmp-tabs__tab--active",
tabpanel: "cmp-tabs__tabpanel--active"
},
stepped: {
tab: "cmp-tabs__tab--stepped",
tabpanel: "cmp-tabs__tabpanel--stepped"
},
label: `.${Tabs.bemBlock}__label`,
description: `.${Tabs.bemBlock}__longdescription`,
qm: `.${Tabs.bemBlock}__questionmark`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ BLOCK cmp-verticaltabs
ELEMENT cmp-verticaltabs__label-container
ELEMENT cmp-verticaltabs__tab
MOD cmp-verticaltabs__tab--active
MOD cmp-verticaltabs__tab--stepped
ELEMENT cmp-verticaltabs__title
ELEMENT cmp-verticaltabs__icon
ELEMENT cmp-verticaltabs__label
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
tab: "cmp-verticaltabs__tab--active",
tabpanel: "cmp-verticaltabs__tabpanel--active"
},
stepped: {
tab: "cmp-verticaltabs__tab--stepped",
tabpanel: "cmp-verticaltabs__tabpanel--stepped"
},
label: `.${VerticalTabs.bemBlock}__label`,
description: `.${VerticalTabs.bemBlock}__longdescription`,
qm: `.${VerticalTabs.bemBlock}__questionmark`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ It is already included by its edit and policy dialogs.
```
BLOCK cmp-adaptiveform-wizard
ELEMENT cmp-adaptiveform-wizard__label
ELEMENT cmp-adaptiveform-wizard__label-container
ELEMENT cmp-adaptiveform-wizard__label-container
ELEMENT cmp-adaptiveform-wizard__tab
MOD cmp-adaptiveform-wizard__tab--active
MOD cmp-adaptiveform-wizard__tab--stepped
ELEMENT cmp-adaptiveform-wizard__wizardpanel
ELEMENT cmp-adaptiveform-wizard__previousNav
ELEMENT cmp-adaptiveform-wizard__nextNav
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@
active: {
tab: "cmp-adaptiveform-wizard__tab--active",
wizardpanel: "cmp-adaptiveform-wizard__wizardpanel--active"
}
},
stepped: {
tab: "cmp-adaptiveform-wizard__tab--stepped",
wizardpanel: "cmp-adaptiveform-wizard__wizardpanel--stepped",
}
};

_active;
Expand Down Expand Up @@ -72,6 +76,48 @@
}
}

addSteppedClass() {
const tabs = this.getCachedTabs();
const wizardPanels = this.getCachedWizardPanels();
const activeChildId = this.getActiveWizardTabId(tabs)
const activeTab = this.getTabNavElementById(activeChildId);
if (activeTab.classList.contains(this.constructor.selectors.active.tab)) {
activeTab.classList.add(this.constructor.selectors.stepped.tab);

const correspondingPanel = Array.from(wizardPanels).find(panel =>
panel.getAttribute("aria-labelledby") === activeTab.id
);

if (correspondingPanel) {
correspondingPanel.classList.add(this.constructor.selectors.stepped.wizardpanel);
}
}
}

getTabNavElementById(tabId) {
let tabs = this.getCachedTabs();
if (tabs) {
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].id === tabId) {
return tabs[i];
}
}
}
}

getActiveWizardTabId(tabs) {
if (tabs) {
var result = tabs[0].id;
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].classList.contains(this.constructor.selectors.active.tab)) {
result = tabs[i].id;
break;
}
}
return result;
}
}

/**
* Returns the index of the active tab, if no tab is active returns 0
*
Expand Down Expand Up @@ -105,6 +151,7 @@
*/
navigate(index) {
this._active = index;
this.addSteppedClass();
this.refreshActive();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
tab: "cmp-adaptiveform-wizard__tab--active",
wizardpanel: "cmp-adaptiveform-wizard__wizardpanel--active"
},
stepped: {
tab: "cmp-adaptiveform-wizard__tab--stepped",
wizardpanel: "cmp-adaptiveform-wizard__wizardpanel--stepped",
},
label: `.${Wizard.bemBlock}__label`,
description: `.${Wizard.bemBlock}__longdescription`,
qm: `.${Wizard.bemBlock}__questionmark`,
Expand Down Expand Up @@ -331,7 +335,7 @@
this.navigate(index);
this.focusWithoutScroll(this.getCachedTabs()[index]);
}

#syncWizardNavLabels() {
const tabs = this.getCachedTabs();
const wizardPanels = this.getCachedWizardPanels();
Expand Down Expand Up @@ -382,12 +386,21 @@
}
} else {
let beforeTabNavElementId = childView.getInstanceManager().children[instanceIndex - 1].element.id + Wizard.#tabIdSuffix
let beforeElement = this.#getTabNavElementById(beforeTabNavElementId);
let beforeElement = this.getTabNavElementById(beforeTabNavElementId);
beforeElement.after(navigationTabToBeRepeated);
}
this.cacheElements(this._elements.self);
let repeatedWizardPanel = this.#getWizardPanelElementById(childView.id + Wizard.#wizardPanelIdSuffix);
repeatedWizardPanel.setAttribute("aria-labelledby", childView.id + Wizard.#tabIdSuffix);

const steppedTabClass = Array.from(navigationTabToBeRepeated.classList).find(cls => cls.includes('--stepped'));
if (steppedTabClass) {
navigationTabToBeRepeated.classList.remove(steppedTabClass);
}
const steppedWizardPanelClass = Array.from(repeatedWizardPanel.classList).find(cls => cls.includes('--stepped'));
if (steppedWizardPanelClass) {
repeatedWizardPanel.classList.remove(steppedWizardPanelClass);
}
this.refreshActive();
this.#getTabIndexById();
if (childView.getInstanceManager().getModel().minOccur != undefined && childView.getInstanceManager().children.length > childView.getInstanceManager().getModel().minOccur) {
Expand All @@ -400,7 +413,7 @@
let removedTabPanelId = removedInstanceView.element.id + Wizard.#wizardPanelIdSuffix;
let removedTabNavId = removedTabPanelId.substring(0, removedTabPanelId.lastIndexOf("__")) + Wizard.#tabIdSuffix;
let wizardPanelElement = this.#getWizardPanelElementById(removedTabPanelId);
let tabNavElement = this.#getTabNavElementById(removedTabNavId);
let tabNavElement = this.getTabNavElementById(removedTabNavId);
tabNavElement.remove();
wizardPanelElement.remove();
this.children.splice(this.children.indexOf(removedInstanceView), 1);
Expand Down Expand Up @@ -448,25 +461,14 @@
let tabId = childView.element.id + Wizard.#tabIdSuffix;
let wizardPanelId = childView.element.id + Wizard.#wizardPanelIdSuffix;
let instanceManagerId = childView.getInstanceManager().getId();
let navigationTabToBeRepeated = this.#getTabNavElementById(tabId);
let navigationTabToBeRepeated = this.getTabNavElementById(tabId);
let wizardPanelToBeRepeated = this.#getWizardPanelElementById(wizardPanelId)
this._templateHTML[instanceManagerId] = {};
this._templateHTML[instanceManagerId]['navigationTab'] = navigationTabToBeRepeated;
this._templateHTML[instanceManagerId]['targetWizardPanel'] = wizardPanelToBeRepeated;
}
}

#getTabNavElementById(tabId) {
let tabs = this.getCachedTabs();
if (tabs) {
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].id === tabId) {
return tabs[i];
}
}
}
}

#getWizardPanelElementById(wizardPanelId) {
let wizardPanels = this.getCachedWizardPanels();
if (wizardPanels) {
Expand Down Expand Up @@ -516,7 +518,7 @@
}

updateChildVisibility(visible, state) {
this.updateVisibilityOfNavigationElement(this.#getTabNavElementById(state.id + Wizard.#tabIdSuffix), visible);
this.updateVisibilityOfNavigationElement(this.getTabNavElementById(state.id + Wizard.#tabIdSuffix), visible);
let activeTabNavElement = this.getCachedTabs()[this._active];
this.#setNavigationRange();
this.#hideUnhideNavButtons(this._active);
Expand Down
28 changes: 28 additions & 0 deletions ui.frontend/src/view/FormTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,29 @@ class FormTabs extends FormPanel {
*/
navigate(tabId) {
this.#_active = tabId;
this.addSteppedClass(tabId);
this.#refreshActive();
}


addSteppedClass(tabId) {
var tabs = this.#getCachedTabs();
var tabpanels= this.#getCachedTabPanels();
const activeTabId = this.getActiveTabId(tabs);
const activeTabElement = this.#getTabNavElementById(activeTabId);
if (activeTabElement.classList.contains(this.#_selectors.active.tab)) {
activeTabElement.classList.add(this.#_selectors.stepped.tab);

const correspondingPanel = Array.from(tabpanels).find(panel =>
panel.getAttribute("aria-labelledby") === activeTabElement.id
);

if (correspondingPanel) {
correspondingPanel.classList.add(this.#_selectors.stepped.tabpanel);
}
}
}

/**
* Returns the id of the active tab, if no tab is active returns 0th element id
*
Expand Down Expand Up @@ -384,6 +404,14 @@ class FormTabs extends FormPanel {
this.#cacheElements(this._elements.self);
var repeatedTabPanel = this.#getTabPanelElementById(childView.id + this.#tabPanelIdSuffix);
repeatedTabPanel.setAttribute("aria-labelledby", childView.id + this.#tabIdSuffix);
const steppedTabClass = Array.from(navigationTabToBeRepeated.classList).find(cls => cls.includes('--stepped'));
if (steppedTabClass) {
navigationTabToBeRepeated.classList.remove(steppedTabClass);
}
const steppedTabpanelClass = Array.from(repeatedTabPanel.classList).find(cls => cls.includes('--stepped'));
if (steppedTabpanelClass) {
repeatedTabPanel.classList.remove(steppedTabpanelClass);
}
this.#bindEventsToTab(navigationTabToBeRepeated.id);
this.#refreshActive();
if (childView.getInstanceManager().getModel().minOccur != undefined && childView.getInstanceManager().children.length > childView.getInstanceManager().getModel().minOccur) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,41 @@ describe("Form with Accordion Container with repeatable elements", () => {
getAccordionButtons().should('have.length', 8);
})
});

it("if item-1 is repeated, the repeated instance should not have stepped class", () => {
getItemDivs().should('have.length', 5);
getAccordionPanels().should('have.length', 5);
getAccordionButtons().should('have.length', 5);
getExpandedPanelDiv().should('have.length', 1);
getExpandedButtonDiv().should('have.length', 1);
getAccordionButtonsAtIndex(0).should('have.class', 'cmp-accordion__button--expanded');
getAccordionPanelsAtIndex(0).should('have.class', 'cmp-accordion__panel--expanded');
cy.get("button").contains("+RP1").click().then(() => {
getItemDivs().should('have.length', 6);
getAccordionPanels().should('have.length', 6);
getAccordionButtons().should('have.length', 6);
getExpandedPanelDiv().should('have.length', 1);
getExpandedButtonDiv().should('have.length', 1);
getAccordionButtonsAtIndex(1).should('have.class', 'cmp-accordion__button--expanded');
getAccordionPanelsAtIndex(1).should('have.class', 'cmp-accordion__panel--expanded');
getAccordionButtonsAtIndex(0).should('have.class', 'cmp-accordion__button--stepped');
getAccordionPanelsAtIndex(0).should('have.class', 'cmp-accordion__panel--stepped');
});
cy.get("button").contains("+RP1").click().then(() => {
getItemDivs().should('have.length', 7);
getAccordionPanels().should('have.length', 7);
getAccordionButtons().should('have.length', 7);
getExpandedPanelDiv().should('have.length', 1);
getExpandedButtonDiv().should('have.length', 1);
getAccordionButtonsAtIndex(2).should('have.class', 'cmp-accordion__button--expanded');
getAccordionPanelsAtIndex(2).should('have.class', 'cmp-accordion__panel--expanded');
getAccordionButtonsAtIndex(1).should('have.class', 'cmp-accordion__button--stepped');
getAccordionPanelsAtIndex(1).should('have.class', 'cmp-accordion__panel--stepped');
getAccordionButtonsAtIndex(0).should('have.class', 'cmp-accordion__button--stepped');
getAccordionPanelsAtIndex(0).should('have.class', 'cmp-accordion__panel--stepped');
});
cy.expectNoConsoleErrors();
})
})

describe("Form with Accordion Container with nested repeatable elements", () => {
Expand Down
3 changes: 3 additions & 0 deletions ui.tests/test-module/specs/tabsontop/tabsontop.runtime.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,13 @@ describe("Form with Panel Container", () => {
tab2().should('have.class', 'cmp-tabs__tab--active');
tab2().should('have.attr', 'aria-selected', 'true');
tab1().should('have.attr', 'aria-selected', 'false');
tab1().should('have.class', 'cmp-tabs__tab--stepped');
tab1().click();
tab1().should('have.class', 'cmp-tabs__tab--active');
tab1().should('have.class', 'cmp-tabs__tab--stepped');
tab1().should('have.attr', 'aria-selected', 'true');
tab2().should('have.attr', 'aria-selected', 'false');
tab2().should('have.class', 'cmp-tabs__tab--stepped');
});

it("switch tab in runtime using keyboard", () => {
Expand Down
Loading