Shared:ContextMenu:Add max width context menu. Added trimming of overflowing text with ellipsis.

This commit is contained in:
Vlada Gazizova 2024-06-07 12:46:07 +03:00
parent 87a95b6d42
commit a0483cbd4c
5 changed files with 73 additions and 24 deletions

View File

@ -26,7 +26,7 @@
import styled, { css } from "styled-components"; import styled, { css } from "styled-components";
import { Base, TTheme } from "../../themes"; import { Base, TTheme } from "../../themes";
import { tablet, mobile, getCorrectFourValuesStyle } from "../../utils"; import { mobile, isMobile, getCorrectFourValuesStyle } from "../../utils";
const styledTabletView = css<{ articleWidth: number }>` const styledTabletView = css<{ articleWidth: number }>`
position: fixed; position: fixed;
@ -116,11 +116,22 @@ const StyledContextMenu = styled.div<{
${(props) => props.changeView && styledMobileView} ${(props) => props.changeView && styledMobileView}
} }
@media ${mobile} {
${(props) => props.changeView && styledMobileView}
}
.scroll-body { .scroll-body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
padding-inline-end: 0 !important;
} }
${!isMobile() &&
css`
max-width: calc(100vw - 32px);
`}
} }
.contextmenu-header { .contextmenu-header {
@ -212,6 +223,11 @@ const StyledContextMenu = styled.div<{
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
${!isMobile() &&
css`
max-width: calc(100vw - 32px);
`}
} }
.p-contextmenu .p-submenu-list { .p-contextmenu .p-submenu-list {
@ -291,22 +307,23 @@ const StyledContextMenu = styled.div<{
cursor: default !important; cursor: default !important;
margin: ${(props) => props.theme.menuItem.separator.margin}; margin: ${(props) => props.theme.menuItem.separator.margin};
height: ${(props) => props.theme.menuItem.separator.height}; height: ${(props) => props.theme.menuItem.separator.height};
width: ${(props) => props.theme.menuItem.separator.width};
&:hover { &:hover {
cursor: default !important; cursor: default !important;
} }
@media ${mobile} {
margin-right: 8px !important;
width: calc(100% - 24px) !important;
}
} }
.p-contextmenu .p-menuitem { .p-contextmenu .p-menuitem {
position: relative; position: relative;
margin: ${(props) => props.theme.dropDownItem.margin}; margin: ${(props) => props.theme.dropDownItem.margin};
min-width: max-content; max-width: calc(-32px + 100vw);
width: fit-content;
min-width: inherit;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
.p-contextmenu .scroll-body .p-menuitem { .p-contextmenu .scroll-body .p-menuitem {
@ -399,12 +416,23 @@ StyledContextMenu.defaultProps = {
export const StyledList = styled.ul<{ export const StyledList = styled.ul<{
listHeight: number; listHeight: number;
widthSubMenu: null | number;
}>` }>`
& > :first-child { & > :first-child {
.scroll-body { .scroll-body {
height: ${(props) => `${props.listHeight}px`}; height: ${(props) => `${props.listHeight}px`};
} }
} }
& > :nth-child(1) {
${(props) =>
props.widthSubMenu &&
css`
.p-menuitem {
max-width: ${`${props.widthSubMenu}px`};
}
`}
}
`; `;
export { StyledContextMenu }; export { StyledContextMenu };

View File

@ -296,7 +296,7 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
} }
} }
if (menuRef.current) { if (menuRef.current) {
menuRef.current.style.left = `${left}px`; menuRef.current.style.left = `${left || 16}px`;
menuRef.current.style.top = `${top}px`; menuRef.current.style.top = `${top}px`;
if (!mobileView) menuRef.current.style.width = `${width}px`; if (!mobileView) menuRef.current.style.width = `${width}px`;

View File

@ -67,6 +67,7 @@ const SubMenu = (props: {
const [model, setModel] = useState(props?.model); const [model, setModel] = useState(props?.model);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [activeItem, setActiveItem] = useState<ContextMenuType | null>(null); const [activeItem, setActiveItem] = useState<ContextMenuType | null>(null);
const [widthSubMenu, setWidthSubMenu] = useState<null | number>(null);
const subMenuRef = useRef<HTMLUListElement>(null); const subMenuRef = useRef<HTMLUListElement>(null);
@ -185,25 +186,33 @@ const SubMenu = (props: {
viewport.width - containerOffsetLeft - itemOuterWidth; viewport.width - containerOffsetLeft - itemOuterWidth;
const freeSpaceLeft = containerOffsetLeft; const freeSpaceLeft = containerOffsetLeft;
const submenuListMargin = 4; const submenuListMargin = 4;
const sectionPadding = 17; const sectionPadding = 16;
if (isRtl) { if (isRtl) {
if (
!root &&
freeSpaceLeft > freeSpaceRight &&
subListWidth > containerOffsetLeft
) {
// If the menu extends beyond the screen
subMenuRef.current.style.width = `${containerOffsetLeft - submenuListMargin - sectionPadding}px`;
}
if ( if (
subListWidth < containerOffsetLeft || subListWidth < containerOffsetLeft ||
(!root && freeSpaceLeft > freeSpaceRight) (!root && freeSpaceLeft > freeSpaceRight)
) { ) {
subMenuRef.current.style.left = `${-1 * subListWidth}px`; subMenuRef.current.style.left = `${-1 * subListWidth}px`;
if (!root && subListWidth > containerOffsetLeft) {
// If the menu extends beyond the screen
const newWidth =
containerOffsetLeft - submenuListMargin - sectionPadding;
subMenuRef.current.style.width = `${newWidth}px`;
setWidthSubMenu(newWidth);
}
} else { } else {
subMenuRef.current.style.left = `${itemOuterWidth}px`; subMenuRef.current.style.left = `${itemOuterWidth}px`;
if (!root && subListWidth > freeSpaceRight) {
// If the menu extends beyond the screen
const newWidth = freeSpaceRight - 3 * submenuListMargin;
subMenuRef.current.style.width = `${newWidth}px`;
setWidthSubMenu(newWidth);
}
} }
} }
@ -212,8 +221,20 @@ const SubMenu = (props: {
viewport.width - DomHelpers.calculateScrollbarWidth(); viewport.width - DomHelpers.calculateScrollbarWidth();
if (!isRtl) { if (!isRtl) {
if (notEnoughWidthRight && containerOffsetLeft > subListWidth) { if (notEnoughWidthRight && freeSpaceLeft > freeSpaceRight) {
subMenuRef.current.style.left = `${-1 * subListWidth}px`; subMenuRef.current.style.left = `${-1 * subListWidth}px`;
if (
notEnoughWidthRight &&
!root &&
subListWidth > containerOffsetLeft
) {
// If the menu extends beyond the screen
const newWidth = containerOffsetLeft - 12;
subMenuRef.current.style.width = `${newWidth}px`;
setWidthSubMenu(newWidth);
}
} else { } else {
subMenuRef.current.style.left = `${itemOuterWidth}px`; subMenuRef.current.style.left = `${itemOuterWidth}px`;
@ -227,6 +248,7 @@ const SubMenu = (props: {
sectionPadding; sectionPadding;
subMenuRef.current.style.width = `${newWidth}px`; subMenuRef.current.style.width = `${newWidth}px`;
setWidthSubMenu(newWidth);
} }
} }
} }
@ -504,6 +526,7 @@ const SubMenu = (props: {
ref={subMenuRef} ref={subMenuRef}
className={`${className} not-selectable`} className={`${className} not-selectable`}
listHeight={height + paddingList} listHeight={height + paddingList}
widthSubMenu={widthSubMenu}
> >
<Scrollbar style={{ height: listHeight }}>{submenu}</Scrollbar> <Scrollbar style={{ height: listHeight }}>{submenu}</Scrollbar>
{submenuLower} {submenuLower}

View File

@ -2760,9 +2760,8 @@ export const getBaseTheme = () => {
}, },
separator: { separator: {
borderBottom: `1px solid ${grayLightMid} !important`, borderBottom: `1px solid ${grayLightMid} !important`,
margin: "6px 0px 6px 16px !important", margin: "6px 16px !important",
height: "1px !important", height: "1px !important",
width: "calc(100% - 16px) !important",
}, },
text: { text: {
header: { header: {

View File

@ -2739,9 +2739,8 @@ const Dark: TTheme = {
}, },
separator: { separator: {
borderBottom: `1px solid #474747 !important`, borderBottom: `1px solid #474747 !important`,
margin: "6px 0px 6px 16px !important", margin: "6px 16px !important",
height: "1px !important", height: "1px !important",
width: "calc(100% - 16px) !important",
}, },
text: { text: {
header: { header: {