Skip to content

Commit f8bcadc

Browse files
committed
IBX-10533: Quick action btn manager for handling & displaying multiple btns
1 parent 553a512 commit f8bcadc

File tree

11 files changed

+144
-33
lines changed

11 files changed

+144
-33
lines changed

src/bundle/Resources/encore/ibexa.js.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const layout = [
4040
path.resolve(__dirname, '../public/js/scripts/admin.picker.js'),
4141
path.resolve(__dirname, '../public/js/scripts/admin.notifications.modal.js'),
4242
path.resolve(__dirname, '../public/js/scripts/sidebar/side.panel.js'),
43+
path.resolve(__dirname, '../public/js/scripts/quick.action.manager.js'),
4344
path.resolve(__dirname, '../public/js/scripts/admin.location.add.translation.js'),
4445
path.resolve(__dirname, '../public/js/scripts/admin.form.autosubmit.js'),
4546
path.resolve(__dirname, '../public/js/scripts/admin.anchor.navigation'),

src/bundle/Resources/public/js/scripts/admin.back.to.top.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,36 @@
11
(function (global, doc) {
22
const backToTopBtn = doc.querySelector('.ibexa-back-to-top__btn');
3+
const backToTop = doc.querySelector('.ibexa-back-to-top');
34
const backToTopAnchor = doc.querySelector('.ibexa-back-to-top-anchor');
45
const backToTopScrollContainer = doc.querySelector('.ibexa-back-to-top-scroll-container');
56

67
if (!backToTopBtn || !backToTopAnchor || !backToTopScrollContainer) {
78
return;
89
}
910

11+
const checkIsVisible = () => {
12+
if (!backToTop) {
13+
return false;
14+
}
15+
16+
return backToTopBtn.classList.contains('ibexa-back-to-top__btn--visible');
17+
};
18+
1019
const backToTopBtnTitle = backToTopBtn.querySelector('.ibexa-back-to-top__title');
1120
let currentBackToTopAnchorHeight = backToTopAnchor.offsetHeight;
1221
const setBackToTopBtnTextVisibility = (container) => {
1322
const isTitleVisible = Math.abs(container.scrollHeight - container.scrollTop - container.clientHeight) <= 2;
23+
const shouldBeVisible = container.scrollTop !== 0;
24+
25+
if (backToTopBtn.classList.contains('ibexa-back-to-top__btn--visible') && !shouldBeVisible) {
26+
backToTopBtn.classList.remove('ibexa-back-to-top__btn--visible');
27+
}
28+
29+
if (!backToTopBtn.classList.contains('ibexa-back-to-top__btn--visible') && shouldBeVisible) {
30+
backToTopBtn.classList.add('ibexa-back-to-top__btn--visible');
31+
global.ibexa.adminUiConfig.quickActionManager.recalculateButtonsLayout();
32+
}
1433

15-
backToTopBtn.classList.toggle('ibexa-back-to-top__btn--visible', container.scrollTop !== 0);
1634
backToTopBtn.classList.toggle('ibexa-btn--no-text', !isTitleVisible);
1735
backToTopBtnTitle.classList.toggle('ibexa-back-to-top__title--visible', isTitleVisible);
1836
};
@@ -37,6 +55,14 @@
3755

3856
setBackToTopBtnTextVisibility(backToTopScrollContainer);
3957
});
58+
const config = {
59+
name: 'back-to-top',
60+
zIndex: 10,
61+
selector: backToTop,
62+
priority: 100,
63+
checkVisibility: checkIsVisible,
64+
};
4065

66+
global.ibexa.adminUiConfig.quickActionManager.registerButton(config);
4167
resizeObserver.observe(backToTopAnchor);
4268
})(window, window.document);

src/bundle/Resources/public/js/scripts/core/backdrop.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
if (this.backdrop) {
2929
this.backdrop.remove();
3030
this.backdrop = null;
31+
this.extraClasses = [];
3132
}
3233
}
3334

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
(function (global) {
2+
let registeredActionButtons = [];
3+
4+
const QuickActionManager = (() => {
5+
const registerButton = (config) => {
6+
if (!config || !config.selector || registeredActionButtons.some((btn) => btn.name === config.name)) {
7+
return;
8+
}
9+
10+
registeredActionButtons = [...registeredActionButtons, config];
11+
recalculateButtonsLayout();
12+
};
13+
const unregisterButton = (name) => {
14+
registeredActionButtons = registeredActionButtons.filter((btn) => btn.name !== name);
15+
recalculateButtonsLayout();
16+
};
17+
18+
const recalculateButtonsLayout = () => {
19+
const sortedButtons = registeredActionButtons.sort((a, b) => a.priority - b.priority);
20+
const buttonsToRender = sortedButtons.filter((el) => {
21+
if (el.checkVisibility && typeof el.checkVisibility === 'function') {
22+
const isVisible = el.checkVisibility();
23+
24+
return isVisible;
25+
}
26+
27+
return false;
28+
});
29+
30+
buttonsToRender.forEach((buttonConfig, index) => {
31+
const { selector } = buttonConfig;
32+
33+
if (!selector.style.transition) {
34+
selector.style.transition = 'all 0.3s ease-in-out';
35+
}
36+
37+
selector.style.position = 'fixed';
38+
selector.style.right = '2rem';
39+
selector.style.zIndex = buttonConfig.zIndex || 1040;
40+
41+
const bottomPosition = `${index === 0 ? 2 : (index + 1) * 3.2}rem`;
42+
selector.style.bottom = bottomPosition;
43+
});
44+
};
45+
return {
46+
registerButton,
47+
unregisterButton,
48+
recalculateButtonsLayout,
49+
};
50+
})();
51+
52+
window.ibexa = window.ibexa || {};
53+
global.ibexa.adminUiConfig.quickActionManager = QuickActionManager;
54+
})(window);

src/bundle/Resources/public/js/scripts/sidebar/side.panel.js

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,42 @@
44
'.ibexa-side-panel .ibexa-btn--close, .ibexa-side-panel .ibexa-side-panel__btn--cancel',
55
);
66
const sidePanelTriggers = [...doc.querySelectorAll('.ibexa-side-panel-trigger')];
7-
const backdrop = new ibexa.core.Backdrop();
8-
const removeBackdrop = () => {
9-
backdrop.hide();
7+
const panelBackdrops = new Map(); // Mapa przechowująca powiązania panel -> backdrop
8+
const defaultBackdrop = new ibexa.core.Backdrop();
9+
const removeBackdrop = (sidePanel) => {
10+
const backdrop = panelBackdrops.get(sidePanel) || defaultBackdrop;
11+
12+
backdrop.remove();
1013
doc.body.classList.remove('ibexa-scroll-disabled');
14+
15+
if (panelBackdrops.has(sidePanel)) {
16+
panelBackdrops.delete(sidePanel);
17+
}
1118
};
12-
const showBackdrop = () => {
13-
backdrop.show();
19+
const showBackdrop = (sidePanel) => {
20+
if (sidePanel.dataset.backdropClasses) {
21+
const extraClasses = sidePanel.dataset.backdropClasses.split(' ').filter(Boolean);
22+
const newBackdrop = new ibexa.core.Backdrop({ extraClasses });
23+
24+
newBackdrop.show();
25+
panelBackdrops.set(sidePanel, newBackdrop);
26+
} else {
27+
defaultBackdrop.show();
28+
panelBackdrops.set(sidePanel, defaultBackdrop);
29+
}
30+
1431
doc.body.classList.add('ibexa-scroll-disabled');
1532
};
1633
const toggleSidePanelVisibility = (sidePanel) => {
1734
const shouldBeVisible = sidePanel.classList.contains(CLASS_HIDDEN);
1835
const handleClickOutside = (event) => {
19-
if (event.target.classList.contains('ibexa-backdrop')) {
36+
const currentBackdrop = panelBackdrops.get(sidePanel);
37+
38+
if (event.target.classList.contains('ibexa-backdrop') && event.target === currentBackdrop.get()) {
39+
event.stopPropagation();
2040
sidePanel.classList.add(CLASS_HIDDEN);
21-
doc.body.removeEventListener('click', handleClickOutside, false);
22-
removeBackdrop();
41+
doc.body.removeEventListener('click', handleClickOutside, { capture: true });
42+
removeBackdrop(sidePanel);
2343

2444
if (sidePanel.dataset?.closeReload === 'true') {
2545
global.location.reload();
@@ -30,11 +50,11 @@
3050
sidePanel.classList.toggle(CLASS_HIDDEN, !shouldBeVisible);
3151

3252
if (shouldBeVisible) {
33-
doc.body.addEventListener('click', handleClickOutside, false);
34-
showBackdrop();
53+
doc.body.addEventListener('click', handleClickOutside, { capture: true });
54+
showBackdrop(sidePanel);
3555
} else {
36-
doc.body.removeEventListener('click', handleClickOutside, false);
37-
removeBackdrop();
56+
doc.body.removeEventListener('click', handleClickOutside, { capture: true });
57+
removeBackdrop(sidePanel);
3858
}
3959
};
4060

src/bundle/Resources/public/scss/_back-to-top.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
.ibexa-back-to-top {
2-
position: fixed;
3-
bottom: calculateRem(16px);
4-
right: calculateRem(32px);
5-
62
.btn.ibexa-back-to-top__btn {
73
height: calculateRem(62px);
84
min-width: calculateRem(62px);

src/bundle/Resources/public/scss/_tabs.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@
3030
}
3131
}
3232

33+
&--no-corner {
34+
.ibexa-tabs__link {
35+
font-weight: 600;
36+
background-color: $ibexa-color-light-400;
37+
}
38+
}
39+
3340
&--hidden {
3441
display: none;
3542
}

src/bundle/Resources/views/themes/admin/ui/component/tab/tabs.html.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
active_tab,
1717
hide_toggler: hide_toggler|default(false),
1818
include_tab_more: include_tab_more|default(false),
19+
tab_corner_disabled: tab_corner_disabled|default(false),
1920
} %}
2021
{% block tabs_list_after %}
2122
{{ tabs_list_after_content }}

src/bundle/Resources/views/themes/admin/ui/component/tab/tabs_header.html.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
label: tab.label,
1818
active: tab == active_tab,
1919
has_error: tab.has_error|default(false),
20+
tab_corner_disabled: tab_corner_disabled|default(false),
2021
} %}
2122
{% endfor %}
2223
{% endblock %}

src/bundle/Resources/views/themes/admin/ui/component/tab/tabs_tab.html.twig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@
1010
label: tab.label,
1111
} %}
1212
{% endblock %}
13-
{% include '@ibexadesign/ui/component/tab/tab_corner.html.twig' %}
13+
{% if not tab_corner_disabled|default(false) %}
14+
{% include '@ibexadesign/ui/component/tab/tab_corner.html.twig' %}
15+
{% endif %}
1416
</li>

0 commit comments

Comments
 (0)