Skip to content

Commit 7c8831f

Browse files
[O2B-1077] Keep scroll in popover after re-rendering (#1300)
1 parent 5985685 commit 7c8831f

5 files changed

Lines changed: 35 additions & 5 deletions

File tree

lib/public/components/Filters/common/filtersPanelPopover.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const filtersToggleTrigger = () => h('button#openFilterToggle.btn.btn.btn-primar
3232
*
3333
* @return {Component} the filters panel
3434
*/
35-
const filtersToggleContent = (filteringModel, columns) => h('.w-l.h-100.scroll-y', [
35+
const filtersToggleContent = (filteringModel, columns) => h('.w-l.scroll-y', [
3636
h('.f4.ph3.pv2', 'Filters'),
3737
Object.entries(columns)
3838
.filter(([_, column]) => column.filter)
@@ -62,6 +62,8 @@ export const filtersPanelPopover = (filterModel, activeColumns) => h('.flex-row.
6262
{
6363
...PopoverTriggerPreConfiguration.click,
6464
anchor: PopoverAnchors.RIGHT_START,
65+
// Set children size to true because filter panel has an overflow scroll
66+
setChildrenSize: true,
6567
},
6668
),
6769
]);

lib/public/components/common/popover/PopoverEngine.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ class PopoverEngine {
142142
* @param {{x: number, y: number}} displayZoneMargins the margins to apply at the edge of the display zone
143143
* @param {{main: MainAxisPopoverPosition, cross: CrossAxisPopoverPosition}} position the position of the popover relative to the trigger
144144
* @param {{main: BoundingBoxProjector, cross: BoundingBoxProjector}} projectors the axis projectors
145+
* @param {boolean} setChildrenSize if true, children component size will be set to the popover size
145146
*/
146147
constructor(
147148
trigger,
@@ -150,6 +151,7 @@ class PopoverEngine {
150151
displayZoneMargins,
151152
position,
152153
projectors,
154+
setChildrenSize,
153155
) {
154156
this._popover = popover;
155157

@@ -164,6 +166,8 @@ class PopoverEngine {
164166

165167
this._displayBoundingBox = displayBoundingBox;
166168
this._displayZoneMargins = displayZoneMargins;
169+
170+
this._setChildrensize = setChildrenSize;
167171
}
168172

169173
/**
@@ -222,6 +226,11 @@ class PopoverEngine {
222226
}
223227

224228
this._mainAxisProjector.setSize(this._popover.style, `${mainAxisSize}px`);
229+
if (this._setChildrensize) {
230+
for (const children of this._popover.children) {
231+
this._mainAxisProjector.setSize(children.style, `${mainAxisSize}px`);
232+
}
233+
}
225234

226235
this._refreshPopoverBoundingBox();
227236
}
@@ -235,6 +244,11 @@ class PopoverEngine {
235244
resizeAlongCrossAxis() {
236245
if (this._popoverSizeCrossAxis > this._availableSpaceInCrossAxis) {
237246
this._crossAxisProjector.setSize(this._popover.style, `${this._availableSpaceInCrossAxis}px`);
247+
if (this._setChildrensize) {
248+
for (const children of this._popover.children) {
249+
this._crossAxisProjector.setSize(children.style, `${this._availableSpaceInCrossAxis}px`);
250+
}
251+
}
238252

239253
this._refreshPopoverBoundingBox();
240254
}
@@ -280,7 +294,7 @@ class PopoverEngine {
280294

281295
const crossAxisPosition = Math.max(
282296
this._crossAxisProjector.getPosition(this._displayBoundingBox)
283-
+ this._crossAxisProjector.getPosition(this._displayZoneMargins),
297+
+ this._crossAxisProjector.getPosition(this._displayZoneMargins),
284298
Math.min(
285299
this._availableSpaceInCrossAxis - this._popoverSizeCrossAxis,
286300
targetStartCrossAxis,
@@ -420,9 +434,10 @@ class PopoverEngine {
420434
* @param {BoundingBox} displayBoundingBox the bounding box of the display zone, representing the limits where the popover may be drawn
421435
* @param {{x: number, y: number}} displayZoneMargins the margins to apply at the edge of the display zone
422436
* @param {PopoverAnchor} anchor the anchor to place the popover
437+
* @param {boolean} setChildrenSize if true, children component size will be set to the popover size
423438
* @return {PopoverEngine} the created popover engine
424439
*/
425-
export const createPopoverEngine = (trigger, popover, displayBoundingBox, displayZoneMargins, anchor) => {
440+
export const createPopoverEngine = (trigger, popover, displayBoundingBox, displayZoneMargins, anchor, setChildrenSize) => {
426441
// Top and Bottom are the 6 first anchors
427442
const mainAxisProjector = anchor / 6 < 1 ? verticalProjector : horizontalProjector;
428443
const crossAxisProjector = anchor / 6 < 1 ? horizontalProjector : verticalProjector;
@@ -440,5 +455,6 @@ export const createPopoverEngine = (trigger, popover, displayBoundingBox, displa
440455
displayZoneMargins,
441456
{ main: mainAxisPosition, cross: crossAxisPosition },
442457
{ main: mainAxisProjector, cross: crossAxisProjector },
458+
setChildrenSize,
443459
);
444460
};

lib/public/components/common/popover/dropdown.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export const dropdown = (
4040
...PopoverTriggerPreConfiguration.click,
4141
anchor: alignment === 'left' ? PopoverAnchors.BOTTOM_START : PopoverAnchors.BOTTOM_END,
4242
onVisibilityChange: configuration.onVisibilityChange,
43+
// Set children size to true because dropdown has an overflow scroll
44+
setChildrenSize: true,
4345
},
4446
);
4547
};

lib/public/components/common/popover/popover.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { h } from '/js/src/index.js';
1515
import { createPortal } from '../../../utilities/createPortal.js';
1616
import { getUniqueId } from '../../../utilities/getUniqueId.js';
1717
import { createPopoverEngine } from './PopoverEngine.js';
18+
import { StatefulComponent } from '../StatefulComponent.js';
1819

1920
/**
2021
* Default margin to apply at the edge of the display zone
@@ -68,12 +69,15 @@ const DEFAULT_DISPLAY_ZONE_MARGIN = { left: 15, top: 15 };
6869
* @property {popoverShowConditionCallback} [showCondition] function called before showing the popover
6970
* @property {string[]|string} [popoverClass] css classes to apply to the popover (in addition to the default ones)
7071
* @property {{x: number, y: number}} displayZoneMargins the margins to apply at the edges to display zone
72+
* @property {boolean} [setChildrenSize] if true, popover children elements will have width and height set to the size of the popover. Set this
73+
* flag to true if popover content has a fixed size that should be 100% of the popover, because if using style of 100% height/width the
74+
* scroll will not be kept between renders
7175
*/
7276

7377
/**
7478
* Component to display a popover triggered on specific actions
7579
*/
76-
class PopoverComponent {
80+
class PopoverComponent extends StatefulComponent {
7781
/**
7882
* Constructor
7983
*
@@ -82,6 +86,8 @@ class PopoverComponent {
8286
* @param {PopoverConfiguration} configuration the popover options
8387
*/
8488
constructor({ attrs: { trigger, content, configuration } }) {
89+
super();
90+
8591
this._triggerComponent = trigger;
8692
this._contentCompoenent = content;
8793

@@ -135,6 +141,7 @@ class PopoverComponent {
135141
},
136142
this._displayZoneMargins,
137143
this._anchor,
144+
this._setChildrenSize,
138145
);
139146
engine.reset();
140147
engine.fitAndPosition();
@@ -154,6 +161,7 @@ class PopoverComponent {
154161
this._isVisible = visibility;
155162
this.updatePopover();
156163
this._onVisibilityChange(visibility);
164+
this.notify();
157165
}
158166
}
159167

@@ -278,6 +286,7 @@ class PopoverComponent {
278286
showCondition,
279287
popoverClass = [],
280288
displayZoneMargins = {},
289+
setChildrenSize = false,
281290
} = configuration;
282291
this._anchor = anchor;
283292
this._onTriggerNodeChange = onTriggerNodeChange.bind(this);
@@ -289,6 +298,7 @@ class PopoverComponent {
289298
...DEFAULT_DISPLAY_ZONE_MARGIN,
290299
...displayZoneMargins,
291300
};
301+
this._setChildrenSize = setChildrenSize;
292302
}
293303
}
294304

lib/public/utilities/createPortal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class Portal {
7676
if (this.container.contains(this.rootNode)) {
7777
// Unmount the node in order for its lifecycle functions to be called
7878
mount(this.rootNode, () => null, false);
79-
this.rootNode.removeEventListener('click', this._propagateClick());
79+
this.rootNode.removeEventListener('click', this._propagateClick);
8080
this.rootNode.remove();
8181
}
8282
}

0 commit comments

Comments
 (0)