Skip to content

Commit e71b663

Browse files
authored
feat: add portalContainer prop for elements rendered via createPortal (#2275)
1 parent e536079 commit e71b663

File tree

13 files changed

+163
-98
lines changed

13 files changed

+163
-98
lines changed

packages/main/src/components/ActionSheet/index.tsx

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ import styles from './ActionSheet.jss';
2828

2929
export interface ActionSheetPropTypes extends Omit<ResponsivePopoverPropTypes, 'children'> {
3030
/**
31-
* Defines the actions of the <code>ActionSheet</code>. <br><b>Note:</b> Although this slot accepts all HTML Elements, it is strongly recommended that you only use `Buttons` in order to preserve the intended design.
31+
* Defines the actions of the `ActionSheet`.
32+
*
33+
* __Note:__ Although this slot accepts all HTML Elements, it is strongly recommended that you only use `Buttons` in order to preserve the intended design.
3234
*/
3335
children?: ReactElement<ButtonPropTypes> | ReactElement<ButtonPropTypes>[];
3436
/**
@@ -48,6 +50,12 @@ export interface ActionSheetPropTypes extends Omit<ResponsivePopoverPropTypes, '
4850
ariaLabel?: string;
4951
};
5052
};
53+
/**
54+
* Defines where modals are rendered into via `React.createPortal`.
55+
*
56+
* Defaults to: `document.body`
57+
*/
58+
portalContainer?: Element;
5159
}
5260

5361
const useStyles = createUseStyles(styles, { name: 'ActionSheet' });
@@ -94,27 +102,28 @@ if (isPhone()) {
94102
*/
95103
const ActionSheet = forwardRef((props: ActionSheetPropTypes, ref: RefObject<Ui5ResponsivePopoverDomRef>) => {
96104
const {
105+
a11yConfig,
106+
allowTargetOverlap,
107+
alwaysShowHeader,
97108
children,
98-
style,
99-
slot,
100109
className,
101-
allowTargetOverlap,
110+
footer,
111+
header,
102112
headerText,
113+
hideArrow,
103114
horizontalAlign,
104115
initialFocus,
105116
modal,
106-
hideArrow,
107117
placementType,
118+
portalContainer,
119+
showCancelButton,
120+
slot,
121+
style,
108122
verticalAlign,
109-
footer,
110-
header,
111123
onAfterClose,
112124
onAfterOpen,
113125
onBeforeClose,
114-
onBeforeOpen,
115-
showCancelButton,
116-
alwaysShowHeader,
117-
a11yConfig
126+
onBeforeOpen
118127
} = props;
119128
const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
120129
const classes = useStyles();
@@ -231,13 +240,14 @@ const ActionSheet = forwardRef((props: ActionSheetPropTypes, ref: RefObject<Ui5R
231240
)}
232241
</div>
233242
</ResponsivePopover>,
234-
document.body
243+
portalContainer
235244
);
236245
});
237246

238247
ActionSheet.defaultProps = {
239248
showCancelButton: true,
240-
alwaysShowHeader: true
249+
alwaysShowHeader: true,
250+
portalContainer: document.body
241251
};
242252

243253
ActionSheet.displayName = 'ActionSheet';

packages/main/src/components/AnalyticalTable/ColumnHeader/ColumnHeaderContainer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ interface ColumnHeaderContainerProps {
3838
resizeInfo: Record<string, unknown>;
3939
reactWindowRef: MutableRefObject<any>;
4040
isRtl: boolean;
41+
portalContainer: Element;
4142
}
4243

4344
const useStyles = createUseStyles(styles, { name: 'Resizer' });
@@ -59,7 +60,8 @@ export const ColumnHeaderContainer = forwardRef((props: ColumnHeaderContainerPro
5960
overscanCountHorizontal,
6061
resizeInfo,
6162
reactWindowRef,
62-
isRtl
63+
isRtl,
64+
portalContainer
6365
} = props;
6466
const columnVirtualizer = useVirtual({
6567
size: visibleColumnsWidth.length,
@@ -132,6 +134,7 @@ export const ColumnHeaderContainer = forwardRef((props: ColumnHeaderContainerPro
132134
isDraggable={column.canReorder && !resizeInfo.isResizingColumn}
133135
virtualColumn={virtualColumn}
134136
isRtl={isRtl}
137+
portalContainer={portalContainer}
135138
>
136139
{column.render('Header')}
137140
</ColumnHeader>

packages/main/src/components/AnalyticalTable/ColumnHeader/ColumnHeaderModal.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export interface ColumnHeaderModalProperties {
3333
open: boolean;
3434
setPopoverOpen: (open: boolean) => void;
3535
targetRef: RefObject<any>;
36+
portalContainer: Element;
3637
}
3738

3839
const styles = {
@@ -49,7 +50,7 @@ const styles = {
4950
const useStyles = createUseStyles(styles, { name: 'ColumnHeaderModal' });
5051

5152
export const ColumnHeaderModal = (props: ColumnHeaderModalProperties) => {
52-
const { column, onSort, onGroupBy, open, setPopoverOpen, targetRef } = props;
53+
const { column, onSort, onGroupBy, open, setPopoverOpen, targetRef, portalContainer } = props;
5354
const classes = useStyles();
5455
const showFilter = column.canFilter;
5556
const showGroup = column.canGroupBy;
@@ -197,7 +198,7 @@ export const ColumnHeaderModal = (props: ColumnHeaderModalProperties) => {
197198
)}
198199
</List>
199200
</Popover>,
200-
document.body
201+
portalContainer
201202
);
202203
};
203204
ColumnHeaderModal.displayName = 'ColumnHeaderModal';

packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ import React, {
1313
MouseEventHandler,
1414
KeyboardEventHandler,
1515
ReactNode,
16-
ReactNodeArray,
17-
useCallback,
18-
useMemo,
1916
useRef,
2017
useState
2118
} from 'react';
@@ -38,7 +35,8 @@ export interface ColumnHeaderProps {
3835
headerTooltip: string;
3936
virtualColumn: VirtualItem;
4037
isRtl: boolean;
41-
children: ReactNode | ReactNodeArray;
38+
children: ReactNode | ReactNode[];
39+
portalContainer: Element;
4240

4341
//getHeaderProps()
4442
id: string;
@@ -113,7 +111,8 @@ export const ColumnHeader: FC<ColumnHeaderProps> = (props: ColumnHeaderProps) =>
113111
columnIndex,
114112
visibleColumnIndex,
115113
onClick,
116-
onKeyDown
114+
onKeyDown,
115+
portalContainer
117116
} = props;
118117

119118
const isFiltered = column.filterValue && column.filterValue.length > 0;
@@ -238,6 +237,7 @@ export const ColumnHeader: FC<ColumnHeaderProps> = (props: ColumnHeaderProps) =>
238237
targetRef={targetRef}
239238
open={popoverOpen}
240239
setPopoverOpen={setPopoverOpen}
240+
portalContainer={portalContainer}
241241
/>
242242
)}
243243
</div>

packages/main/src/components/AnalyticalTable/VerticalResizer.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ interface VerticalResizerProps {
4444
internalRowHeight: number;
4545
hasPopInColumns: boolean;
4646
popInRowHeight: number;
47+
portalContainer: Element;
4748
}
4849

4950
const isTouchEvent = (e, touchEvent) => {
@@ -54,7 +55,15 @@ const isTouchEvent = (e, touchEvent) => {
5455
};
5556

5657
export const VerticalResizer = (props: VerticalResizerProps) => {
57-
const { analyticalTableRef, dispatch, extensionsHeight, internalRowHeight, hasPopInColumns, popInRowHeight } = props;
58+
const {
59+
analyticalTableRef,
60+
dispatch,
61+
extensionsHeight,
62+
internalRowHeight,
63+
hasPopInColumns,
64+
popInRowHeight,
65+
portalContainer
66+
} = props;
5867
const classes = useStyles();
5968
const startY = useRef(null);
6069
const verticalResizerRef = useRef(null);
@@ -162,7 +171,7 @@ export const VerticalResizer = (props: VerticalResizerProps) => {
162171
className={classes.resizer}
163172
style={{ top: resizerPosition.top, left: resizerPosition.left, width: resizerPosition.width }}
164173
/>,
165-
document.body
174+
portalContainer
166175
)}
167176
</div>
168177
);

packages/main/src/components/AnalyticalTable/index.tsx

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,12 @@ export interface AnalyticalTablePropTypes extends Omit<CommonProps, 'title'> {
246246
* Defines whether a subcomponent should be rendered as expandable container or directly at the bottom of the row.
247247
*/
248248
alwaysShowSubComponent?: boolean;
249+
/**
250+
* Defines where modals and other elements which should be mounted outside of the DOM hierarchy are rendered into via `React.createPortal`.
251+
*
252+
* Defaults to: `document.body`
253+
*/
254+
portalContainer?: Element;
249255

250256
// events
251257
/**
@@ -321,52 +327,53 @@ const useStyles = createUseStyles(styles, { name: 'AnalyticalTable' });
321327
*/
322328
const AnalyticalTable = forwardRef((props: AnalyticalTablePropTypes, ref: Ref<HTMLDivElement>) => {
323329
const {
324-
columns,
330+
alternateRowColor,
331+
alwaysShowSubComponent,
325332
className,
326-
style,
327-
tooltip,
333+
columnOrder,
334+
columns,
335+
extension,
336+
filterable,
337+
globalFilterValue,
338+
groupBy,
339+
groupable,
328340
header,
341+
highlightField,
342+
infiniteScroll,
343+
infiniteScrollThreshold,
344+
isTreeTable,
329345
loading,
330-
groupBy,
331-
selectionMode,
332-
selectionBehavior,
333-
onRowSelected,
334-
onRowClick,
335-
onSort,
336-
reactTableOptions,
337-
tableHooks,
338-
subRowsKey,
339-
onGroup,
340-
rowHeight,
341-
selectedRowIds,
342-
LoadingComponent,
343-
onRowExpandChange,
344-
noDataText,
345-
NoDataComponent,
346-
visibleRows,
347-
visibleRowCountMode,
346+
markNavigatedRow,
348347
minRows,
349-
isTreeTable,
350-
alternateRowColor,
348+
noDataText,
351349
overscanCount,
352350
overscanCountHorizontal,
351+
portalContainer,
352+
reactTableOptions,
353+
renderRowSubComponent,
354+
rowHeight,
353355
scaleWidthMode,
354-
withRowHighlight,
355-
highlightField,
356-
withNavigationHighlight,
357-
markNavigatedRow,
358-
groupable,
356+
selectedRowIds,
357+
selectionBehavior,
358+
selectionMode,
359359
sortable,
360-
filterable,
361-
infiniteScroll,
362-
infiniteScrollThreshold,
360+
style,
361+
subRowsKey,
362+
tableHooks,
363+
tableInstance,
364+
tooltip,
365+
visibleRowCountMode,
366+
visibleRows,
367+
withNavigationHighlight,
368+
withRowHighlight,
369+
onGroup,
363370
onLoadMore,
364-
extension,
365-
columnOrder,
366-
renderRowSubComponent,
367-
alwaysShowSubComponent,
368-
globalFilterValue,
369-
tableInstance
371+
onRowClick,
372+
onRowExpandChange,
373+
onRowSelected,
374+
onSort,
375+
LoadingComponent,
376+
NoDataComponent
370377
} = props;
371378

372379
const classes = useStyles();
@@ -750,6 +757,7 @@ const AnalyticalTable = forwardRef((props: AnalyticalTablePropTypes, ref: Ref<HT
750757
onDragEnd={handleOnDragEnd}
751758
dragOver={dragOver}
752759
isRtl={isRtl}
760+
portalContainer={portalContainer}
753761
/>
754762
)
755763
);
@@ -830,6 +838,7 @@ const AnalyticalTable = forwardRef((props: AnalyticalTablePropTypes, ref: Ref<HT
830838
dispatch={dispatch}
831839
extensionsHeight={extensionsHeight}
832840
internalRowHeight={internalRowHeight}
841+
portalContainer={portalContainer}
833842
/>
834843
)}
835844
</div>
@@ -867,7 +876,8 @@ AnalyticalTable.defaultProps = {
867876
alternateRowColor: false,
868877
overscanCountHorizontal: 5,
869878
visibleRowCountMode: TableVisibleRowCountMode.Fixed,
870-
alwaysShowSubComponent: false
879+
alwaysShowSubComponent: false,
880+
portalContainer: document.body
871881
};
872882

873883
export { AnalyticalTable };

packages/main/src/components/FilterBar/FilterDialog.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ export const FilterDialog = (props) => {
5555
onGo,
5656
handleSelectionChange,
5757
handleDialogSearch,
58-
handleDialogCancel
58+
handleDialogCancel,
59+
portalContainer
5960
} = props;
6061
const classes = useStyles();
6162
const [searchString, setSearchString] = useState('');
@@ -281,6 +282,6 @@ export const FilterDialog = (props) => {
281282
{renderGroups()}
282283
</div>
283284
</Dialog>,
284-
document.body
285+
portalContainer
285286
);
286287
};

0 commit comments

Comments
 (0)