Skip to content

Commit

Permalink
Fix primefaces#3753: Menu add popupAlignment property
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware committed May 17, 2023
1 parent c329252 commit 24359ec
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 17 deletions.
35 changes: 23 additions & 12 deletions components/doc/menu/popupdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { DocSectionCode } from '../common/docsectioncode';
import { DocSectionText } from '../common/docsectiontext';

export function PopupDoc(props) {
const menu = useRef(null);
const menuLeft = useRef(null);
const menuRight = useRef(null);
const router = useRouter();
const toast = useRef(null);
const items = [
Expand Down Expand Up @@ -51,8 +52,10 @@ export function PopupDoc(props) {
const code = {
basic: `
<Toast ref={toast}></Toast>
<Menu model={items} popup ref={menu} />
<Button label="Show" icon="pi pi-bars" onClick={(e) => menu.current.toggle(e)} />
<Menu model={items} popup ref={menuLeft} id="popup_menu_left" />
<Button label="Show Left" icon="pi pi-align-left" className="mr-2" onClick={(event) => menuLeft.current.toggle(event)} aria-controls="popup_menu_left" aria-haspopup />
<Menu model={items} popup ref={menuRight} id="popup_menu_right" popupAlignment="right" />
<Button label="Show Right" icon="pi pi-align-right" className="mr-2" onClick={(event) => menuRight.current.toggle(event)} aria-controls="popup_menu_right" aria-haspopup />
`,
javascript: `
import React, { useRef } from 'react';
Expand All @@ -62,7 +65,8 @@ import { Menu } from 'primereact/menu';
import { Toast } from 'primereact/toast';
export default function PopupDoc() {
const menu = useRef(null);
const menuLeft = useRef(null);
const menuRight = useRef(null);
//const router = useRouter();
const toast = useRef(null);
const items = [
Expand Down Expand Up @@ -107,8 +111,10 @@ export default function PopupDoc() {
return (
<div className="card flex justify-content-center">
<Toast ref={toast}></Toast>
<Menu model={items} popup ref={menu} />
<Button label="Show" icon="pi pi-bars" onClick={(e) => menu.current.toggle(e)} />
<Menu model={items} popup ref={menuLeft} id="popup_menu_left" />
<Button label="Show Left" icon="pi pi-align-left" className="mr-2" onClick={(event) => menuLeft.current.toggle(event)} aria-controls="popup_menu_left" aria-haspopup />
<Menu model={items} popup ref={menuRight} id="popup_menu_right" popupAlignment="right" />
<Button label="Show Right" icon="pi pi-align-right" className="mr-2" onClick={(event) => menuRight.current.toggle(event)} aria-controls="popup_menu_right" aria-haspopup />
</div>
)
}
Expand All @@ -122,7 +128,8 @@ import { MenuItem } from 'primereact/menuitem';
import { Toast } from 'primereact/toast';
export default function PopupDoc() {
const menu = useRef<Menu>(null);
const menuLeft = useRef<Menu>(null);
const menuRight = useRef<Menu>(null);
//const router = useRouter();
const toast = useRef<Toast>(null);
const items: MenuItem[] = [
Expand Down Expand Up @@ -167,8 +174,10 @@ export default function PopupDoc() {
return (
<div className="card flex justify-content-center">
<Toast ref={toast}></Toast>
<Menu model={items} popup ref={menu} />
<Button label="Show" icon="pi pi-bars" onClick={(e) => menu.current.toggle(e)} />
<Menu model={items} popup ref={menuLeft} id="popup_menu_left" />
<Button label="Show Left" icon="pi pi-align-left" className="mr-2" onClick={(event) => menuLeft.current.toggle(event)} aria-controls="popup_menu_left" aria-haspopup />
<Menu model={items} popup ref={menuRight} id="popup_menu_right" popupAlignment="right" />
<Button label="Show Right" icon="pi pi-align-right" className="mr-2" onClick={(event) => menuRight.current.toggle(event)} aria-controls="popup_menu_right" aria-haspopup />
</div>
)
}
Expand All @@ -179,13 +188,15 @@ export default function PopupDoc() {
<>
<DocSectionText {...props}>
<p>
Popup mode is enabled by adding <i>popup</i> property and calling <i>toggle</i> method with an event of the target.
Popup mode is enabled by adding <i>popup</i> property and calling <i>toggle</i> method with an event of the target. The <i>popupAlignment</i> property allows you to control how the overlay is aligned with its target.
</p>
</DocSectionText>
<div className="card flex justify-content-center">
<Toast ref={toast}></Toast>
<Menu model={items} popup ref={menu} />
<Button label="Show" icon="pi pi-bars" onClick={(e) => menu.current.toggle(e)} />
<Menu model={items} popup ref={menuLeft} id="popup_menu_left" />
<Button label="Show Left" icon="pi pi-align-left" className="mr-2" onClick={(event) => menuLeft.current.toggle(event)} aria-controls="popup_menu_left" aria-haspopup />
<Menu model={items} popup ref={menuRight} id="popup_menu_right" popupAlignment="right" />
<Button label="Show Right" icon="pi pi-align-right" className="mr-2" onClick={(event) => menuRight.current.toggle(event)} aria-controls="popup_menu_right" aria-haspopup />
</div>
<DocSectionCode code={code} />
</>
Expand Down
4 changes: 2 additions & 2 deletions components/lib/menu/Menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CSSTransition } from '../csstransition/CSSTransition';
import { useOverlayListener, useUnmountEffect } from '../hooks/Hooks';
import { OverlayService } from '../overlayservice/OverlayService';
import { Portal } from '../portal/Portal';
import { classNames, DomHandler, IconUtils, ObjectUtils, ZIndexUtils } from '../utils/Utils';
import { DomHandler, IconUtils, ObjectUtils, ZIndexUtils, classNames } from '../utils/Utils';
import { MenuBase } from './MenuBase';

export const Menu = React.memo(
Expand Down Expand Up @@ -113,7 +113,7 @@ export const Menu = React.memo(

const onEnter = () => {
ZIndexUtils.set('menu', menuRef.current, PrimeReact.autoZIndex, props.baseZIndex || PrimeReact.zIndex['menu']);
DomHandler.absolutePosition(menuRef.current, targetRef.current);
DomHandler.absolutePosition(menuRef.current, targetRef.current, props.popupAlignment);
};

const onEntered = () => {
Expand Down
1 change: 1 addition & 0 deletions components/lib/menu/MenuBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const MenuBase = {
id: null,
model: null,
popup: false,
popupAlignment: 'left',
style: null,
className: null,
autoZIndex: true,
Expand Down
5 changes: 5 additions & 0 deletions components/lib/menu/menu.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export interface MenuProps extends Omit<React.DetailedHTMLProps<React.HTMLAttrib
* @defaultValue false
*/
popup?: boolean | undefined;
/**
* In popup mode determines how the overlay is aligned with its target. Values either 'left' or 'right'.
* @defaultValue left
*/
popupAlignment?: 'left' | 'right';
/**
* Whether to automatically manage layering.
* @defaultValue true
Expand Down
9 changes: 6 additions & 3 deletions components/lib/utils/DomHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export default class DomHandler {
}
}

static absolutePosition(element, target) {
static absolutePosition(element, target, align = 'left') {
if (element && target) {
let elementDimensions = element.offsetParent ? { width: element.offsetWidth, height: element.offsetHeight } : this.getHiddenElementDimensions(element);
let elementOuterHeight = elementDimensions.height;
Expand All @@ -289,8 +289,11 @@ export default class DomHandler {
element.style.transformOrigin = 'top';
}

if (targetOffset.left + targetOuterWidth + elementOuterWidth > viewport.width) left = Math.max(0, targetOffset.left + windowScrollLeft + targetOuterWidth - elementOuterWidth);
else left = targetOffset.left + windowScrollLeft;
const targetOffsetPx = targetOffset.left;
const alignOffset = align === 'left' ? 0 : elementOuterWidth - targetOuterWidth;

if (targetOffsetPx + targetOuterWidth + elementOuterWidth > viewport.width) left = Math.max(0, targetOffsetPx + windowScrollLeft + targetOuterWidth - elementOuterWidth);
else left = targetOffsetPx - alignOffset + windowScrollLeft;

element.style.top = top + 'px';
element.style.left = left + 'px';
Expand Down

0 comments on commit 24359ec

Please sign in to comment.