From dcaa46050d83fdbbd7973ff1a14d6301981a7828 Mon Sep 17 00:00:00 2001 From: balajisoundar Date: Fri, 3 Nov 2023 16:18:13 +0530 Subject: [PATCH] feat: RTL support for input, select and multi-select widget (#28522) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### PR fixes following issue(s) Fixes https://github.com/appsmithorg/appsmith/issues/28469 #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) - Breaking change (fix or feature that would cause existing functionality to not work as expected) - Chore (housekeeping or task changes that don't impact user perception) - This change requires a documentation update > > > ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [x] Manual - [ ] JUnit - [ ] Jest - [x] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed --- .../ClientSide/Widgets/Input/RTL_support.ts | 51 +++++++ .../Widgets/Multiselect/RTL_support.ts | 71 +++++++++ .../ClientSide/Widgets/Select/RTL_support.ts | 69 +++++++++ app/client/src/ce/entities/FeatureFlag.ts | 2 + .../BaseInputWidget/component/index.tsx | 141 +++++++++++------- .../widgets/BaseInputWidget/widget/index.tsx | 6 +- .../widgets/InputWidgetV2/component/index.tsx | 2 + .../widgets/InputWidgetV2/widget/index.tsx | 21 ++- .../component/index.styled.tsx | 54 +++++++ .../MultiSelectWidgetV2/component/index.tsx | 14 +- .../MultiSelectWidgetV2/widget/index.tsx | 18 +++ .../SelectWidget/component/SelectButton.tsx | 3 +- .../SelectWidget/component/index.styled.tsx | 46 ++++++ .../widgets/SelectWidget/component/index.tsx | 12 +- .../src/widgets/SelectWidget/constants.ts | 4 + .../src/widgets/SelectWidget/widget/index.tsx | 18 +++ .../widgets/components/LabelWithTooltip.tsx | 9 +- 17 files changed, 477 insertions(+), 64 deletions(-) create mode 100644 app/client/cypress/e2e/Regression/ClientSide/Widgets/Input/RTL_support.ts create mode 100644 app/client/cypress/e2e/Regression/ClientSide/Widgets/Multiselect/RTL_support.ts create mode 100644 app/client/cypress/e2e/Regression/ClientSide/Widgets/Select/RTL_support.ts diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Input/RTL_support.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Input/RTL_support.ts new file mode 100644 index 0000000000..9370fb7400 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Input/RTL_support.ts @@ -0,0 +1,51 @@ +import { featureFlagIntercept } from "../../../../../support/Objects/FeatureFlags"; +import { + agHelper, + draggableWidgets, + entityExplorer, + propPane, +} from "../../../../../support/Objects/ObjectsCore"; + +describe("Select Widget", () => { + before(() => { + entityExplorer.DragNDropWidget(draggableWidgets.INPUT_V2); + }); + + it("1. Test RTL support", () => { + featureFlagIntercept({ + license_widget_rtl_support_enabled: false, + }); + + agHelper.AssertElementAbsence(".t--property-control-enablertl"); + + featureFlagIntercept({ + license_widget_rtl_support_enabled: true, + }); + + agHelper.RefreshPage(); + + agHelper.Sleep(2000); + + agHelper.AssertElementExist(".t--property-control-enablertl"); + + propPane.TogglePropertyState("Enable RTL", "On"); + + agHelper.AssertElementExist( + ".t--widget-inputwidgetv2 .bp3-input-group.rtl", + ); + + agHelper.AssertElementExist( + ".t--widget-inputwidgetv2 .label-container[dir='rtl']", + ); + + propPane.TogglePropertyState("Enable RTL", "Off"); + + agHelper.AssertElementAbsence( + ".t--widget-inputwidgetv2 .bp3-input-group.rtl", + ); + + agHelper.AssertElementAbsence( + ".t--widget-inputwidgetv2 .label-container[dir='rtl']", + ); + }); +}); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Multiselect/RTL_support.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Multiselect/RTL_support.ts new file mode 100644 index 0000000000..03138ed27c --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Multiselect/RTL_support.ts @@ -0,0 +1,71 @@ +import { featureFlagIntercept } from "../../../../../support/Objects/FeatureFlags"; +import { + agHelper, + draggableWidgets, + entityExplorer, + propPane, +} from "../../../../../support/Objects/ObjectsCore"; + +describe("Select Widget", () => { + before(() => { + entityExplorer.DragNDropWidget(draggableWidgets.MULTISELECT); + }); + + it("1. Test RTL support", () => { + featureFlagIntercept({ + license_widget_rtl_support_enabled: false, + }); + + agHelper.AssertElementAbsence(".t--property-control-enablertl"); + + featureFlagIntercept({ + license_widget_rtl_support_enabled: true, + }); + + agHelper.RefreshPage(); + + agHelper.Sleep(2000); + + agHelper.AssertElementExist(".t--property-control-enablertl"); + + propPane.TogglePropertyState("Enable RTL", "On"); + + agHelper + .GetElement(".t--widget-multiselectwidgetv2 .rc-select-selector") + .click(); + + agHelper + .GetElement( + ".t--widget-multiselectwidgetv2 [data-testid='multiselect-container']", + ) + .should("have.css", "direction", "rtl"); + + agHelper + .GetElement(".t--widget-multiselectwidgetv2 .rc-select-selector") + .should("have.css", "direction", "rtl"); + + agHelper + .GetElement(".multi-select-dropdown input.bp3-input") + .should("have.css", "direction", "rtl"); + + agHelper.GetElement(".rc-select-dropdown [dir='rtl']").should("exist"); + + propPane.TogglePropertyState("Enable RTL", "Off"); + + agHelper + .GetElement( + ".t--widget-multiselectwidgetv2 [data-testid='multiselect-container']", + ) + .should("have.css", "direction", "ltr"); + + agHelper + .GetElement(".t--widget-multiselectwidgetv2 .rc-select-selector") + .should("have.css", "direction", "ltr"); + + agHelper + .GetElement(".multi-select-dropdown input.bp3-input") + .should("have.css", "direction", "ltr"); + + agHelper.GetElement(".rc-select-dropdown [dir='rtl']").should("not.exist"); + }); +}); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Select/RTL_support.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Select/RTL_support.ts new file mode 100644 index 0000000000..f24658a026 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Select/RTL_support.ts @@ -0,0 +1,69 @@ +import { featureFlagIntercept } from "../../../../../support/Objects/FeatureFlags"; +import { + agHelper, + draggableWidgets, + entityExplorer, + propPane, +} from "../../../../../support/Objects/ObjectsCore"; + +describe("Select Widget", () => { + before(() => { + entityExplorer.DragNDropWidget(draggableWidgets.SELECT); + }); + + it("1. Test RTL support", () => { + featureFlagIntercept({ + license_widget_rtl_support_enabled: false, + }); + + agHelper.AssertElementAbsence(".t--property-control-enablertl"); + + featureFlagIntercept({ + license_widget_rtl_support_enabled: true, + }); + + agHelper.RefreshPage(); + + agHelper.Sleep(2000); + + agHelper.AssertElementExist(".t--property-control-enablertl"); + + propPane.TogglePropertyState("Enable RTL", "On"); + + agHelper.GetElement(".t--widget-selectwidget .select-button").click(); + + agHelper + .GetElement(".t--widget-selectwidget .label-container") + .should("have.css", "direction", "rtl"); + + agHelper + .GetElement(".t--widget-selectwidget .select-button") + .should("have.css", "direction", "rtl"); + + agHelper + .GetElement(".select-popover-wrapper input.bp3-input") + .should("have.css", "direction", "rtl"); + + agHelper + .GetElement(".select-popover-wrapper .menu-virtual-list") + .should("have.css", "direction", "rtl"); + + propPane.TogglePropertyState("Enable RTL", "Off"); + + agHelper + .GetElement(".t--widget-selectwidget .label-container") + .should("have.css", "direction", "ltr"); + + agHelper + .GetElement(".t--widget-selectwidget .select-button") + .should("have.css", "direction", "ltr"); + + agHelper + .GetElement(".select-popover-wrapper input.bp3-input") + .should("have.css", "direction", "ltr"); + + agHelper + .GetElement(".select-popover-wrapper .menu-virtual-list") + .should("have.css", "direction", "ltr"); + }); +}); diff --git a/app/client/src/ce/entities/FeatureFlag.ts b/app/client/src/ce/entities/FeatureFlag.ts index 145371d8a6..297b7888f7 100644 --- a/app/client/src/ce/entities/FeatureFlag.ts +++ b/app/client/src/ce/entities/FeatureFlag.ts @@ -28,6 +28,7 @@ export const FEATURE_FLAG = { ab_show_templates_instead_of_blank_canvas_enabled: "ab_show_templates_instead_of_blank_canvas_enabled", release_app_sidebar_enabled: "release_app_sidebar_enabled", + license_widget_rtl_support_enabled: "license_widget_rtl_support_enabled", } as const; export type FeatureFlag = keyof typeof FEATURE_FLAG; @@ -56,6 +57,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = { release_anvil_enabled: false, ab_show_templates_instead_of_blank_canvas_enabled: false, release_app_sidebar_enabled: false, + license_widget_rtl_support_enabled: false, }; export const AB_TESTING_EVENT_KEYS = { diff --git a/app/client/src/widgets/BaseInputWidget/component/index.tsx b/app/client/src/widgets/BaseInputWidget/component/index.tsx index e2ce73fa3f..575cc978d4 100644 --- a/app/client/src/widgets/BaseInputWidget/component/index.tsx +++ b/app/client/src/widgets/BaseInputWidget/component/index.tsx @@ -101,6 +101,38 @@ const InputComponentWrapper = styled((props) => ( line-height: 16px; } } + + ${(props) => + props.inputType === "PASSWORD" && + ` + .password-input { + height: 100%; + width: 36px; + cursor: pointer; + + color: + ${ + props.disabled + ? "var(--wds-color-icon-disabled)" + : "var(--wds-color-icon)" + }; + justify-content: center; + height: 100%; + svg { + width: 20px; + height: 20px; + } + &:hover { + background-color: var(--wds-color-bg-hover); + } + } + `} + + &.rtl { + input { + direction: rtl; + } + } } &&&& { @@ -207,34 +239,6 @@ const InputComponentWrapper = styled((props) => ( return "var(--wds-color-text-light)"; }}; } - - ${(props) => - props.inputType === "PASSWORD" && - ` - & + .bp3-input-action { - height: 100%; - width: 36px; - cursor: pointer; - - .password-input { - color: - ${ - props.disabled - ? "var(--wds-color-icon-disabled)" - : "var(--wds-color-icon)" - }; - justify-content: center; - height: 100%; - svg { - width: 20px; - height: 20px; - } - &:hover { - background-color: var(--wds-color-bg-hover); - } - } - } - `} } & .${Classes.INPUT_GROUP} { @@ -333,6 +337,12 @@ const StyledNumericInput = styled(NumericInput)` } } } + + &.rtl { + input { + direction: rtl; + } + } `; const TextInputWrapper = styled.div<{ @@ -471,13 +481,6 @@ class BaseInputComponent extends React.Component< this.props.onValueChange(valueAsString); }; - getLeftIcon = () => { - if (this.props.iconName && this.props.iconAlign === "left") { - return this.props.iconName; - } - return this.props.leftIcon; - }; - getType(inputType: InputHTMLType = "TEXT") { switch (inputType) { case "PASSWORD": @@ -534,7 +537,10 @@ class BaseInputComponent extends React.Component< allowNumericCharactersOnly autoFocus={this.props.autoFocus} buttonPosition={this.props.buttonPosition} - className={this.props.isLoading ? "bp3-skeleton" : Classes.FILL} + className={ + (this.props.isLoading ? "bp3-skeleton" : Classes.FILL) + + (this.props.rtl ? " rtl" : "") + } disabled={this.props.disabled} inputRef={(el) => { if (this.props.inputRef && el) { @@ -564,6 +570,7 @@ class BaseInputComponent extends React.Component< autoFocus={this.props.autoFocus} autoResize={!!this.props.isDynamicHeightEnabled} className={this.props.isLoading ? "bp3-skeleton" : ""} + dir={this.props.rtl ? "rtl" : "ltr"} disabled={this.props.disabled} maxLength={this.props.maxChars} onBlur={() => this.setFocusState(false)} @@ -585,15 +592,14 @@ class BaseInputComponent extends React.Component< } intent={this.props.intent} - leftIcon={ - this.props.iconName && this.props.iconAlign === "left" - ? this.props.iconName - : this.props.leftIcon - } + leftIcon={this.getLeftIcon()} maxLength={this.props.maxChars} onBlur={() => this.setFocusState(false)} onChange={this.onTextChange} @@ -601,24 +607,47 @@ class BaseInputComponent extends React.Component< onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} placeholder={this.props.placeholder} - rightElement={ - this.props.inputType === "PASSWORD" ? ( - { - this.setState({ showPassword: !this.state.showPassword }); - }} - /> - ) : this.props.iconName && this.props.iconAlign === "right" ? ( - - ) : undefined - } + rightElement={this.getRightIcon()} spellCheck={this.props.spellCheck} type={this.getType(this.props.inputHTMLType)} value={this.props.value} /> ); + + private getLeftIcon = () => { + if (this.props.inputType === "PASSWORD" && this.props.rtl) { + return ( + { + this.setState({ showPassword: !this.state.showPassword }); + }} + /> + ); + } else if (this.props.iconName && this.props.iconAlign === "left") { + return this.props.iconName; + } else { + return this.props.leftIcon; + } + }; + + private getRightIcon = () => { + if (this.props.inputType === "PASSWORD" && !this.props.rtl) { + return ( + { + this.setState({ showPassword: !this.state.showPassword }); + }} + /> + ); + } else if (this.props.iconName && this.props.iconAlign === "right") { + return ; + } + }; + private renderInputComponent = ( inputHTMLType: InputHTMLType = "TEXT", isTextArea: boolean, @@ -693,6 +722,7 @@ class BaseInputComponent extends React.Component< isDynamicHeightEnabled={isDynamicHeightEnabled} loading={isLoading} position={labelPosition} + rtl={this.props.rtl} text={label} width={labelWidth} /> @@ -789,6 +819,7 @@ export interface BaseInputComponentProps extends ComponentProps { errorTooltipBoundary?: string; shouldUseLocale?: boolean; buttonPosition?: NumberInputStepButtonPosition; + rtl?: boolean; } export default BaseInputComponent; diff --git a/app/client/src/widgets/BaseInputWidget/widget/index.tsx b/app/client/src/widgets/BaseInputWidget/widget/index.tsx index 4dc55143f6..4152ce9911 100644 --- a/app/client/src/widgets/BaseInputWidget/widget/index.tsx +++ b/app/client/src/widgets/BaseInputWidget/widget/index.tsx @@ -22,6 +22,7 @@ import type { WidgetBaseConfiguration, WidgetDefaultProps, } from "WidgetProvider/constants"; +import type { PropertyPaneConfig } from "constants/PropertyControlConstants"; class BaseInputWidget< T extends BaseInputWidgetProps, @@ -66,7 +67,9 @@ class BaseInputWidget< }; } - static getPropertyPaneContentConfig() { + static getPropertyPaneContentConfig( + generalProperties: PropertyPaneConfig[] = [], + ) { return [ { sectionName: "Label", @@ -317,6 +320,7 @@ class BaseInputWidget< return props.type !== "PHONE_INPUT_WIDGET"; }, }, + ...generalProperties, ], }, { diff --git a/app/client/src/widgets/InputWidgetV2/component/index.tsx b/app/client/src/widgets/InputWidgetV2/component/index.tsx index 6c50e5c61d..b932dd7885 100644 --- a/app/client/src/widgets/InputWidgetV2/component/index.tsx +++ b/app/client/src/widgets/InputWidgetV2/component/index.tsx @@ -76,6 +76,7 @@ class InputComponent extends React.Component { onKeyDown={this.props.onKeyDown} onValueChange={this.props.onValueChange} placeholder={this.props.placeholder} + rtl={this.props.rtl} showError={this.props.showError} spellCheck={this.props.spellCheck} stepSize={1} @@ -96,6 +97,7 @@ export interface InputComponentProps extends BaseInputComponentProps { boxShadow?: string; accentColor?: string; autoComplete?: string; + rtl?: boolean; } export default InputComponent; diff --git a/app/client/src/widgets/InputWidgetV2/widget/index.tsx b/app/client/src/widgets/InputWidgetV2/widget/index.tsx index 020bfca827..37ff7fc45f 100644 --- a/app/client/src/widgets/InputWidgetV2/widget/index.tsx +++ b/app/client/src/widgets/InputWidgetV2/widget/index.tsx @@ -49,6 +49,7 @@ import type { } from "WidgetProvider/constants"; import { WIDGET_TAGS } from "constants/WidgetConstants"; import { ResponsiveBehavior } from "layoutSystems/common/utils/constants"; +import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; export function defaultValueValidation( value: any, @@ -536,7 +537,23 @@ class InputWidget extends BaseInputWidget { ], }, ], - super.getPropertyPaneContentConfig(), + super.getPropertyPaneContentConfig([ + { + propertyName: "rtl", + label: "Enable RTL", + helpText: "Enables right to left text direction", + controlType: "SWITCH", + isJSConvertible: true, + isBindProperty: true, + isTriggerProperty: false, + validation: { type: ValidationTypes.BOOLEAN }, + hidden: () => { + return !super.getFeatureFlag( + FEATURE_FLAG.license_widget_rtl_support_enabled, + ); + }, + }, + ]), ); } @@ -850,6 +867,7 @@ class InputWidget extends BaseInputWidget { onKeyDown={this.handleKeyDown} onValueChange={this.onValueChange} placeholder={this.props.placeholderText} + rtl={this.props.rtl} showError={!!this.props.isFocused} spellCheck={!!this.props.isSpellCheck} stepSize={1} @@ -869,6 +887,7 @@ export interface InputWidgetProps extends BaseInputWidgetProps { maxNum?: number; minNum?: number; inputText: string; + rtl?: boolean; } export default InputWidget; diff --git a/app/client/src/widgets/MultiSelectWidgetV2/component/index.styled.tsx b/app/client/src/widgets/MultiSelectWidgetV2/component/index.styled.tsx index b65d593e1f..674850f879 100644 --- a/app/client/src/widgets/MultiSelectWidgetV2/component/index.styled.tsx +++ b/app/client/src/widgets/MultiSelectWidgetV2/component/index.styled.tsx @@ -391,6 +391,7 @@ export const MultiSelectContainer = styled.div<{ borderRadius: string; boxShadow?: string; accentColor?: string; + rtl?: boolean; }>` ${labelLayoutStyles} @@ -674,7 +675,60 @@ export const MultiSelectContainer = styled.div<{ : `border: 1px solid var(--wds-color-border-danger); box-shadow: 0px 0px 0px 2px var(--wds-color-border-danger-focus-light) !important;`} } } + + ${(props) => + props.rtl && + ` + &&& { + direction: rtl; + + .rc-select .rc-select-selector { + padding-right: 10px; + padding-left: 36px; + } + + .rc-select-arrow { + right: auto; + left: 0; + } + } + `} `; + +export const RTLStyles = createGlobalStyle<{ dropdownContainer: string }>` + ${(props) => ` + .${props.dropdownContainer} { + &&& { + .rc-select-item { + .rc-select-item-option-state { + .bp3-checkbox { + right: -13px; + padding-left: 24px; + } + } + } + + label.all-options .bp3-control-indicator { + margin-left: 12px; + margin-right: 13px !important; + } + + .bp3-input-group { + .bp3-icon-search { + left: auto; + right: 0px; + } + + input { + padding-right: 34px; + padding-left: 8px !important; + } + } + } + } + `} +`; + export const StyledCheckbox = styled(Checkbox)<{ accentColor?: string; }>` diff --git a/app/client/src/widgets/MultiSelectWidgetV2/component/index.tsx b/app/client/src/widgets/MultiSelectWidgetV2/component/index.tsx index 1f7d80396a..0065cb48db 100644 --- a/app/client/src/widgets/MultiSelectWidgetV2/component/index.tsx +++ b/app/client/src/widgets/MultiSelectWidgetV2/component/index.tsx @@ -15,6 +15,7 @@ import MenuItemCheckBox, { MultiSelectContainer, StyledCheckbox, InputContainer, + RTLStyles, } from "./index.styled"; import type { RenderMode, TextSize } from "constants/WidgetConstants"; import type { Alignment } from "@blueprintjs/core"; @@ -68,6 +69,7 @@ export interface MultiSelectProps onDropdownClose?: () => void; renderMode?: RenderMode; isDynamicHeightEnabled?: boolean; + rtl?: boolean; } const DEBOUNCE_TIMEOUT = 1000; @@ -101,6 +103,7 @@ function MultiSelectComponent({ options, placeholder, renderMode, + rtl, serverSideFiltering, value, widgetId, @@ -238,7 +241,7 @@ function MultiSelectComponent({ ( menu: React.ReactElement>, ) => ( - <> +
{isFilterable ? ( - +
), [ isSelectAll, @@ -277,6 +280,7 @@ function MultiSelectComponent({ isFilterable, filter, onQueryChange, + rtl, ], ); @@ -290,7 +294,11 @@ function MultiSelectComponent({ isValid={isValid} labelPosition={labelPosition} ref={_menu as React.RefObject} + rtl={rtl} > + {rtl ? ( + + ) : null} { + return !super.getFeatureFlag( + FEATURE_FLAG.license_widget_rtl_support_enabled, + ); + }, + }, ], }, { @@ -838,6 +854,7 @@ class MultiSelectWidget extends BaseWidget< options={options} placeholder={this.props.placeholderText as string} renderMode={this.props.renderMode} + rtl={this.props.rtl} serverSideFiltering={this.props.serverSideFiltering} value={values} widgetId={this.props.widgetId} @@ -945,6 +962,7 @@ export interface MultiSelectWidgetProps extends WidgetProps { labelWidth?: number; isDirty?: boolean; labelComponentWidth?: number; + rtl?: boolean; } export default MultiSelectWidget; diff --git a/app/client/src/widgets/SelectWidget/component/SelectButton.tsx b/app/client/src/widgets/SelectWidget/component/SelectButton.tsx index af64293386..020741429f 100644 --- a/app/client/src/widgets/SelectWidget/component/SelectButton.tsx +++ b/app/client/src/widgets/SelectWidget/component/SelectButton.tsx @@ -5,6 +5,7 @@ import { Colors } from "constants/Colors"; import { isEmptyOrNill } from "../../../utils/helpers"; import { StyledDiv } from "./index.styled"; +import { CLASSNAMES } from "../constants"; export interface SelectButtonProps { disabled?: boolean; @@ -31,7 +32,7 @@ function SelectButton(props: SelectButtonProps) { return (