fix: select dropdown

This commit is contained in:
Tolulope Adetula 2022-04-04 06:12:33 +01:00
parent d6ee01ca29
commit 880cb75b3c
11 changed files with 197 additions and 129 deletions

View File

@ -24,9 +24,8 @@
"widgetName": "TreeSelect1",
"displayName": "TreeSelect",
"iconSVG": "/static/media/icon.bd99caba.svg",
"labelText": "Label",
"topRow": 14,
"bottomRow": 22,
"bottomRow": 18,
"parentRowSpace": 10,
"type": "SINGLE_SELECT_TREE_WIDGET",
"hideCard": false,
@ -63,7 +62,7 @@
"isDisabled": false,
"key": "oe8sn5hbxk",
"isRequired": false,
"rightColumn": 18,
"rightColumn": 30,
"widgetId": "p65c0i01ic",
"isVisible": true,
"version": 1,
@ -77,9 +76,8 @@
"widgetName": "MultiTreeSelect2",
"displayName": "Multi TreeSelect",
"iconSVG": "/static/media/icon.b3e28afb.svg",
"labelText": "Label",
"topRow": 31,
"bottomRow": 39,
"bottomRow": 35,
"parentRowSpace": 10,
"type": "MULTI_SELECT_TREE_WIDGET",
"hideCard": false,
@ -117,7 +115,7 @@
"isDisabled": false,
"key": "oe8sn5hbxk",
"isRequired": false,
"rightColumn": 18,
"rightColumn": 30,
"widgetId": "buewtu97rf",
"isVisible": true,
"version": 1,
@ -132,9 +130,8 @@
"isFilterable": true,
"displayName": "Select",
"iconSVG": "/static/media/icon.bd99caba.svg",
"labelText": "Label",
"topRow": 50,
"bottomRow": 58,
"bottomRow": 54,
"parentRowSpace": 10,
"type": "SELECT_WIDGET",
"serverSideFiltering": false,
@ -166,7 +163,7 @@
"isDisabled": false,
"key": "1b9j4l2c65",
"isRequired": false,
"rightColumn": 18,
"rightColumn": 30,
"widgetId": "vnoxjpwd8a",
"isVisible": true,
"version": 1,
@ -178,9 +175,8 @@
"widgetName": "MultiSelect1",
"displayName": "MultiSelect",
"iconSVG": "/static/media/icon.a3495809.svg",
"labelText": "Label",
"topRow": 67,
"bottomRow": 75,
"bottomRow": 71,
"parentRowSpace": 10,
"type": "MULTI_SELECT_WIDGET_V2",
"serverSideFiltering": false,
@ -211,7 +207,7 @@
"isDisabled": false,
"key": "z8p14a1gb8",
"isRequired": false,
"rightColumn": 18,
"rightColumn": 30,
"widgetId": "c2j24v7j6b",
"isVisible": true,
"version": 1,

View File

@ -12,16 +12,16 @@ describe("Dropdown Widget Functionality", function() {
cy.get(formWidgetsPage.selectwidget)
.find(widgetLocators.dropdownSingleSelect)
.invoke("outerWidth")
.should("eq", 147.1875);
cy.get(formWidgetsPage.selectwidget)
.find(widgetLocators.dropdownSingleSelect)
.click({
force: true,
.then((val) => {
cy.get(formWidgetsPage.selectwidget)
.find(widgetLocators.dropdownSingleSelect)
.click({
force: true,
});
cy.get(".select-popover-wrapper")
.invoke("outerWidth")
.should("eq", val);
});
cy.get(".select-popover-wrapper")
.invoke("outerWidth")
.should("eq", 147.1875);
// Menu Button
cy.get(formWidgetsPage.menuButtonWidget)
.find(widgetLocators.menuButton)
@ -40,42 +40,114 @@ describe("Dropdown Widget Functionality", function() {
cy.get(formWidgetsPage.multiselectwidgetv2)
.find(".rc-select-multiple")
.invoke("width")
.should("eq", 147.1875);
cy.get(formWidgetsPage.multiselectwidgetv2)
.find(".rc-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".multi-select-dropdown")
.invoke("width")
.should("eq", 147);
.then((inputWidth) => {
cy.get(formWidgetsPage.multiselectwidgetv2)
.find(".rc-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".multi-select-dropdown")
.invoke("width")
.then((dropdownWidth) => {
expect(Math.floor(inputWidth)).to.equal(Math.floor(dropdownWidth));
});
});
//Multi tree Select
cy.get(formWidgetsPage.multiselecttreeWidget)
.find(".rc-tree-select-multiple")
.invoke("width")
.should("eq", 147.1875);
cy.get(formWidgetsPage.multiselecttreeWidget)
.find(".rc-tree-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".tree-multiselect-dropdown")
.invoke("outerWidth")
.should("eq", 147.1875);
.then((val) => {
cy.get(formWidgetsPage.multiselecttreeWidget)
.find(".rc-tree-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".tree-multiselect-dropdown")
.invoke("outerWidth")
.should("eq", val);
});
// Tree Select
cy.get(formWidgetsPage.singleselecttreeWidget)
.find(".rc-tree-select-single")
.invoke("outerWidth")
.should("eq", 147.1875);
cy.get(formWidgetsPage.singleselecttreeWidget)
.find(".rc-tree-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".single-tree-select-dropdown")
.then((val) => {
cy.get(formWidgetsPage.singleselecttreeWidget)
.find(".rc-tree-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".single-tree-select-dropdown")
.invoke("outerWidth")
.should("eq", val);
});
});
it("Verify dropdown width of Select widgets with Label", function() {
// Select
cy.openPropertyPane("selectwidget");
cy.testJsontext("labeltext", "Label");
cy.get(formWidgetsPage.selectwidget)
.find(widgetLocators.dropdownSingleSelect)
.invoke("outerWidth")
.should("eq", 147.1875);
.then((val) => {
cy.get(formWidgetsPage.selectwidget)
.find(widgetLocators.dropdownSingleSelect)
.click({
force: true,
});
cy.get(".select-popover-wrapper")
.invoke("outerWidth")
.should("eq", val);
});
// MultiSelect
cy.openPropertyPane("multiselectwidgetv2");
cy.testJsontext("labeltext", "Label");
cy.get(formWidgetsPage.multiselectwidgetv2)
.find(".rc-select-multiple")
.invoke("width")
.then((val) => {
cy.get(formWidgetsPage.multiselectwidgetv2)
.find(".rc-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".multi-select-dropdown")
.invoke("width")
.should("eq", val);
});
//Multi tree Select
cy.openPropertyPane("multiselecttreewidget");
cy.testJsontext("labeltext", "Label");
cy.get(formWidgetsPage.multiselecttreeWidget)
.find(".rc-tree-select-multiple")
.invoke("width")
.then((val) => {
cy.get(formWidgetsPage.multiselecttreeWidget)
.find(".rc-tree-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".tree-multiselect-dropdown")
.invoke("outerWidth")
.should("eq", val);
});
// Tree Select
cy.openPropertyPane("singleselecttreewidget");
cy.testJsontext("labeltext", "Label");
cy.get(formWidgetsPage.singleselecttreeWidget)
.find(".rc-tree-select-single")
.invoke("outerWidth")
.then((val) => {
cy.get(formWidgetsPage.singleselecttreeWidget)
.find(".rc-tree-select-selection-search-input")
.first()
.focus({ force: true })
.type("{uparrow}", { force: true });
cy.get(".single-tree-select-dropdown")
.invoke("outerWidth")
.should("eq", val);
});
});
});

View File

@ -82,22 +82,9 @@ export const DropdownStyles = createGlobalStyle<{
id: string;
}>`
${({ dropDownWidth, id }) => `
.multiselecttree-popover-width-${id} {
&&.multiselecttree-popover-width-${id} {
min-width: ${dropDownWidth}px !important;
&.tree-multiselect-dropdown {
min-height: 100px;
position: absolute;
background: #fff;
width: auto;
border-radius: 0px;
margin-top: 5px;
background: white;
box-shadow: 0 6px 20px 0px rgba(0, 0, 0, 0.15) !important;
> div {
min-width: ${dropDownWidth}px;
}
}
width: ${dropDownWidth}px !important;
}
`}
.rc-tree-select-dropdown-hidden {
@ -274,6 +261,15 @@ border: 1px solid #E8E8E8;
}
.tree-multiselect-dropdown {
min-height: 100px;
position: absolute;
background: #fff;
width: auto;
border-radius: 0px;
margin-top: 5px;
background: white;
box-shadow: 0 6px 20px 0px rgba(0, 0, 0, 0.15) !important;
${CommonSelectFilterStyle}
.rc-tree-select-item {
font-size: 16px;

View File

@ -25,7 +25,7 @@ import {
TextSize,
} from "constants/WidgetConstants";
import { Button, Classes, InputGroup } from "@blueprintjs/core";
import { WidgetContainerDiff } from "widgets/WidgetUtils";
import { labelMargin, WidgetContainerDiff } from "widgets/WidgetUtils";
import Icon from "components/ads/Icon";
import { Colors } from "constants/Colors";
@ -122,6 +122,7 @@ function MultiTreeSelectComponent({
const _menu = useRef<HTMLElement | null>(null);
const labelRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const [memoDropDownWidth, setMemoDropDownWidth] = useState(0);
// treeDefaultExpandAll is uncontrolled after first render,
// using this to force render to respond to changes in expandAll
@ -151,15 +152,20 @@ function MultiTreeSelectComponent({
setFilter(event.target.value);
}, []);
const memoDropDownWidth = useMemo(() => {
if (compactMode && labelRef.current) {
const labelWidth = labelRef.current.clientWidth;
const widthDiff = dropDownWidth - labelWidth;
return widthDiff > dropDownWidth ? widthDiff : dropDownWidth;
}
useEffect(() => {
const parentWidth = width - WidgetContainerDiff;
return parentWidth > dropDownWidth ? parentWidth : dropDownWidth;
}, [compactMode, dropDownWidth, width, labelRef.current]);
if (compactMode && labelRef.current) {
const labelWidth = labelRef.current.getBoundingClientRect().width;
const widthDiff = parentWidth - labelWidth - labelMargin;
setMemoDropDownWidth(
widthDiff > dropDownWidth ? widthDiff : dropDownWidth,
);
return;
}
setMemoDropDownWidth(
parentWidth > dropDownWidth ? parentWidth : dropDownWidth,
);
}, [compactMode, dropDownWidth, width, labelText]);
const dropdownRender = useCallback(
(
menu: React.ReactElement<any, string | React.JSXElementConstructor<any>>,

View File

@ -158,37 +158,7 @@ export const DropdownStyles = createGlobalStyle<{
${({ dropDownWidth, id }) => `
.multiselect-popover-width-${id} {
width: ${dropDownWidth}px !important;
&.rc-select-dropdown-hidden {
display: none !important;
}
&.multi-select-dropdown {
min-height: 100px;
position: absolute;
background: #fff;
width: auto;
border-radius: 0px;
margin-top: 5px;
background: white;
box-shadow: 0 6px 20px 0px rgba(0, 0, 0, 0.15) !important;
overflow-x: scroll;
> div {
min-width: ${dropDownWidth}px;
}
.rc-select-item {
font-size: 14px;
padding: 5px 16px;
align-items: center;
cursor: pointer;
width: 100%;
height: 38px;
}
.rc-select-item-option-state {
.bp3-control.bp3-checkbox {
margin-bottom: 0;
}
}
}
min-width: ${dropDownWidth}px !important;
}
`}
.rc-select-dropdown-hidden {
@ -315,9 +285,30 @@ ${({ dropDownWidth, id }) => `
animation-play-state: running;
}
.multi-select-dropdown {
min-height: 100px;
position: absolute;
background: #fff;
width: auto;
border-radius: 0px;
margin-top: 5px;
background: white;
box-shadow: 0 6px 20px 0px rgba(0, 0, 0, 0.15) !important;
overflow-x: scroll;
${CommonSelectFilterStyle}
.rc-select-item {
font-size: 14px;
padding: 5px 16px;
align-items: center;
cursor: pointer;
width: 100%;
height: 38px;
}
.rc-select-item-option-state {
.bp3-control.bp3-checkbox {
margin-bottom: 0;
}
}
}
`;
export const MultiSelectContainer = styled.div<{

View File

@ -26,14 +26,13 @@ import {
} from "constants/WidgetConstants";
import Icon from "components/ads/Icon";
import { Button, Classes, InputGroup } from "@blueprintjs/core";
import { WidgetContainerDiff } from "widgets/WidgetUtils";
import { labelMargin, WidgetContainerDiff } from "widgets/WidgetUtils";
import { Colors } from "constants/Colors";
import { uniqBy } from "lodash";
const menuItemSelectedIcon = (props: { isSelected: boolean }) => {
return <MenuItemCheckBox checked={props.isSelected} />;
};
export interface MultiSelectProps
extends Required<
Pick<
@ -196,19 +195,19 @@ function MultiSelectComponent({
serverSideFiltering ? [options] : [filter, options],
);
useEffect(() => {
const parentWidth = width - WidgetContainerDiff;
if (compactMode && labelRef.current) {
const labelWidth = labelRef.current.clientWidth;
const widthDiff = dropDownWidth - labelWidth;
const labelWidth = labelRef.current.getBoundingClientRect().width;
const widthDiff = parentWidth - labelWidth - labelMargin;
setMemoDropDownWidth(
widthDiff > dropDownWidth ? widthDiff : dropDownWidth,
);
return;
}
const parentWidth = width - WidgetContainerDiff;
setMemoDropDownWidth(
parentWidth > dropDownWidth ? parentWidth : dropDownWidth,
);
}, [compactMode, dropDownWidth, width]);
}, [compactMode, dropDownWidth, width, labelText]);
const onQueryChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
event.stopPropagation();

View File

@ -436,7 +436,7 @@ class MultiSelectWidget extends BaseWidget<
getPageView() {
const options = isArray(this.props.options) ? this.props.options : [];
const dropDownWidth = MinimumPopupRows * this.props.parentColumnSpace;
const minDropDownWidth = MinimumPopupRows * this.props.parentColumnSpace;
const { componentWidth } = this.getComponentDimensions();
const values: LabelValueType[] = this.props.selectedOptions
? this.props.selectedOptions.map((o) =>
@ -456,7 +456,7 @@ class MultiSelectWidget extends BaseWidget<
)
}
disabled={this.props.isDisabled ?? false}
dropDownWidth={dropDownWidth}
dropDownWidth={minDropDownWidth}
dropdownStyle={{
zIndex: Layers.dropdownModalWidget,
}}

View File

@ -22,6 +22,7 @@ import {
import Fuse from "fuse.js";
import { WidgetContainerDiff } from "widgets/WidgetUtils";
import SelectButton from "./SelectButton";
import { labelMargin } from "../../WidgetUtils";
const FUSE_OPTIONS = {
shouldSort: true,
@ -218,18 +219,16 @@ class SelectComponent extends React.Component<
getDropdownWidth = () => {
const parentWidth = this.props.width - WidgetContainerDiff;
const dropDownWidth =
parentWidth > this.props.dropDownWidth
? parentWidth
: this.props.dropDownWidth;
if (this.props.compactMode && this.labelRef.current) {
const labelWidth = this.labelRef.current.clientWidth;
const widthDiff = dropDownWidth - labelWidth;
const labelWidth = this.labelRef.current.getBoundingClientRect().width;
const widthDiff = parentWidth - labelWidth - labelMargin;
return widthDiff > this.props.dropDownWidth
? widthDiff
: this.props.dropDownWidth;
}
return dropDownWidth;
return parentWidth > this.props.dropDownWidth
? parentWidth
: this.props.dropDownWidth;
};
render() {

View File

@ -82,8 +82,9 @@ export const DropdownStyles = createGlobalStyle<{
id: string;
}>`
${({ dropDownWidth, id }) => `
.treeselect-popover-width-${id} {
&&.treeselect-popover-width-${id} {
min-width: ${dropDownWidth}px !important;
width: ${dropDownWidth}px !important;
}
`}
.rc-tree-select-dropdown-hidden {

View File

@ -24,7 +24,7 @@ import {
TextSize,
} from "constants/WidgetConstants";
import { Button, Classes, InputGroup } from "@blueprintjs/core";
import { WidgetContainerDiff } from "widgets/WidgetUtils";
import { labelMargin, WidgetContainerDiff } from "widgets/WidgetUtils";
import Icon from "components/ads/Icon";
import { Colors } from "constants/Colors";
export interface TreeSelectProps
@ -118,6 +118,7 @@ function SingleSelectTreeComponent({
const labelRef = useRef<HTMLDivElement>(null);
const _menu = useRef<HTMLElement | null>(null);
const inputRef = useRef<HTMLInputElement>(null);
const [memoDropDownWidth, setMemoDropDownWidth] = useState(0);
// treeDefaultExpandAll is uncontrolled after first render,
// using this to force render to respond to changes in expandAll
@ -152,15 +153,20 @@ function SingleSelectTreeComponent({
setFilter(event.target.value);
}, []);
const memoDropDownWidth = useMemo(() => {
if (compactMode && labelRef.current) {
const labelWidth = labelRef.current.clientWidth;
const widthDiff = dropDownWidth - labelWidth;
return widthDiff > dropDownWidth ? widthDiff : dropDownWidth;
}
useEffect(() => {
const parentWidth = width - WidgetContainerDiff;
return parentWidth > dropDownWidth ? parentWidth : dropDownWidth;
}, [compactMode, dropDownWidth, width, labelRef.current]);
if (compactMode && labelRef.current) {
const labelWidth = labelRef.current.getBoundingClientRect().width;
const widthDiff = parentWidth - labelWidth - labelMargin;
setMemoDropDownWidth(
widthDiff > dropDownWidth ? widthDiff : dropDownWidth,
);
return;
}
setMemoDropDownWidth(
parentWidth > dropDownWidth ? parentWidth : dropDownWidth,
);
}, [compactMode, dropDownWidth, width, labelText]);
const dropdownRender = useCallback(
(

View File

@ -74,6 +74,8 @@ export const hexToRgb = (
};
// Padding between PositionContainer and Widget
export const WidgetContainerDiff = 8;
// MArgin between Label and Input
export const labelMargin = 5;
export const hexToRgba = (color: string, alpha: number) => {
const value = hexToRgb(color);
return `rgba(${value.r}, ${value.g}, ${value.b}, ${alpha});`;