From ea04404de9c35ef9630366e04e74c2193acc092c Mon Sep 17 00:00:00 2001 From: Pawan Kumar Date: Thu, 18 Aug 2022 11:56:07 +0530 Subject: [PATCH] fix: Reskinning Input Widgets (#15546) * update checkbox * fix margin in checkbox * fix color bug * fix border radius * fixes * remove unused imports * bug fixes * ui fixes * code review feedback fixes * css updates for toggle * fix bg bug in checkbox * fix disabled checkbox style * update styles for radio and switch * update label align * add hover interaction for switch * add wds css variables * add error state * add error state * fix css variable * fix css * fix checkbox group column height * move checkbox icons to assets * update input * fix input * fix input * fix input fix * fix disalbed icon color * empty commit to deploy again * address review feedbacks * fix font in dropdown * fix colors * fix search icon alignment * fix space in right cross icon * fix colors and label alignment * fix margin top in tooltip * replace red color with css variable * Json form field spec fix * fix css variable typo in checkbox * fix css variable typo in checkbox * fix label spec Co-authored-by: Aishwarya UR --- app/client/cypress/support/commands.js | 7 +- app/client/src/components/ads/Dropdown.tsx | 2 + .../src/components/ads/LabelWithTooltip.tsx | 7 +- .../src/components/wds/Checkbox/index.tsx | 2 +- app/client/src/theme/wds.css | 16 +++- .../BaseInputWidget/component/index.tsx | 93 +++++++++++++++---- .../CheckboxWidget/component/index.tsx | 4 +- .../component/CurrencyCodeDropdown.tsx | 81 ++++++++++++++-- .../CurrencyInputWidget/component/index.tsx | 5 +- .../component/CurrencyCodeDropdown.tsx | 9 +- .../component/ISDCodeDropdown.tsx | 80 ++++++++++++++-- 11 files changed, 254 insertions(+), 52 deletions(-) diff --git a/app/client/cypress/support/commands.js b/app/client/cypress/support/commands.js index 8992abf1ff..36474dab32 100644 --- a/app/client/cypress/support/commands.js +++ b/app/client/cypress/support/commands.js @@ -1662,6 +1662,7 @@ Cypress.Commands.add("checkLabelForWidget", (options) => { const isCompact = options.isCompact; const widgetSelector = `.t--widget-${widgetName}`; const labelSelector = `${widgetSelector} label`; + const labelContainer = `${widgetSelector} .label-container`; const containerSelector = `${widgetSelector} ${options.containerSelector}`; const labelPositionSelector = ".t--property-control-position"; const labelAlignmentRightSelector = @@ -1715,7 +1716,7 @@ Cypress.Commands.add("checkLabelForWidget", (options) => { .type(`${labelWidth}`); cy.wait(300); // Assert the label width - cy.get(labelSelector) + cy.get(labelContainer) .first() .should("have.css", "width", `${parentColumnSpace * labelWidth}px`); // Increase the label width @@ -1724,7 +1725,7 @@ Cypress.Commands.add("checkLabelForWidget", (options) => { .click(); // Assert the increased label width cy.wait(300); - cy.get(labelSelector) + cy.get(labelContainer) .first() .should("have.css", "width", `${parentColumnSpace * (labelWidth + 1)}px`); // Decrease the label width @@ -1733,7 +1734,7 @@ Cypress.Commands.add("checkLabelForWidget", (options) => { .click(); cy.wait(300); // Assert the decreased label width - cy.get(labelSelector) + cy.get(labelContainer) .first() .should("have.css", "width", `${parentColumnSpace * labelWidth}px`); diff --git a/app/client/src/components/ads/Dropdown.tsx b/app/client/src/components/ads/Dropdown.tsx index 0595e778fd..04ef9807cb 100644 --- a/app/client/src/components/ads/Dropdown.tsx +++ b/app/client/src/components/ads/Dropdown.tsx @@ -120,6 +120,7 @@ export type DropdownProps = CommonComponentProps & customBadge?: JSX.Element; selectedHighlightBg?: string; showEmptyOptions?: boolean; + portalContainer?: HTMLElement; }; export interface DefaultDropDownValueNodeProps { selected: DropdownOption | DropdownOption[]; @@ -1268,6 +1269,7 @@ export default function Dropdown(props: DropdownProps) { onInteraction={(state) => !disabled && setIsOpen(state)} popoverClassName={`${props.className} none-shadow-popover`} portalClassName={props.portalClassName} + portalContainer={props.portalContainer} position={Position.BOTTOM_LEFT} usePortal={!props.dontUsePortal} > diff --git a/app/client/src/components/ads/LabelWithTooltip.tsx b/app/client/src/components/ads/LabelWithTooltip.tsx index b3339c66a3..17199e3cb1 100644 --- a/app/client/src/components/ads/LabelWithTooltip.tsx +++ b/app/client/src/components/ads/LabelWithTooltip.tsx @@ -126,6 +126,7 @@ export const LabelContainer = styled.div` } ${({ alignment, compact, inline, optionCount, position, width }) => ` + ${width && `width: ${width}px`}; ${ position !== LabelPosition.Top && (position === LabelPosition.Left || compact) @@ -137,7 +138,6 @@ export const LabelContainer = styled.div` ${!width && `width: ${LABEL_DEFAULT_WIDTH_RATE}%`}; ${alignment === Alignment.RIGHT && `justify-content: flex-end`}; label { - ${width && `width: ${width}px`}; ${ alignment === Alignment.RIGHT ? `text-align: right` @@ -169,7 +169,9 @@ export const StyledLabel = styled(Label)` }}; ${({ color, disabled, fontSize, fontStyle }) => ` - color: ${disabled ? Colors.GREY_8 : color || "inherit"}; + color: ${ + disabled ? "var(--wds-color-text-disabled)" : color || "inherit" + }; font-size: ${fontSize ?? "inherit"}; font-weight: ${ fontStyle?.includes(FontStyleTypes.BOLD) ? "bold" : "normal" @@ -183,7 +185,6 @@ export const StyledLabel = styled(Label)` const ToolTipIcon = styled(IconWrapper)` cursor: help; - margin-top: 1.5px; &&&:hover { svg { path { diff --git a/app/client/src/components/wds/Checkbox/index.tsx b/app/client/src/components/wds/Checkbox/index.tsx index d6bff8e74c..ad710baf81 100644 --- a/app/client/src/components/wds/Checkbox/index.tsx +++ b/app/client/src/components/wds/Checkbox/index.tsx @@ -81,7 +81,7 @@ const Checkbox = styled(BlueprintCheckbox)` // hover on checked + disabled &.bp3-control.bp3-checkbox:hover input:checked:disabled ~ .bp3-control-indicator { box-shadow: 0px 0px 0px 1px var(--wds-color-border-disabled); - background-color: var(--wds-color-disabled) !important; + background-color: var(--wds-color-bg-disabled) !important; } // checked diff --git a/app/client/src/theme/wds.css b/app/client/src/theme/wds.css index a460f0750a..d6ff4084e8 100644 --- a/app/client/src/theme/wds.css +++ b/app/client/src/theme/wds.css @@ -1,18 +1,24 @@ :root { --wds-color-border: #E0DEDE; --wds-color-border-hover: #B3B3B3; - + --wds-color-border-disabled: #E0DEDE; --wds-color-border-danger: #D91921; --wds-color-border-danger-hover: #B90707; - --wds-color-border-disabled: #E0DEDE; - + --wds-color-bg-hover: #EBEBEB; --wds-color-bg-strong: #E0DEDE; --wds-color-bg-strong-hover: #B3B3B3; - --wds-color-bg-disabled: #F3F3F3; --wds-color-bg-disabled-strong: #A9A7A7; - --wds-color-bg-danger: #D91921; --wds-color-bg-danger-hover: #B90707; + + --wds-color-icon: #858282; + --wds-color-icon-disabled: #A9A7A7; + + --wds-color-text: #090707; + --wds-color-text-danger: #D91921; + --wds-color-text-light: #716E6E; + --wds-color-text-disabled: #A9A7A7; + --wds-color-text-disabled-light: #CAC7C7; } diff --git a/app/client/src/widgets/BaseInputWidget/component/index.tsx b/app/client/src/widgets/BaseInputWidget/component/index.tsx index 04b29ddb65..36407c6b2f 100644 --- a/app/client/src/widgets/BaseInputWidget/component/index.tsx +++ b/app/client/src/widgets/BaseInputWidget/component/index.tsx @@ -75,16 +75,23 @@ const InputComponentWrapper = styled((props) => ( }>` ${labelLayoutStyles} + cursor: ${({ disabled }) => (disabled ? "not-allowed" : "auto")}; .${Classes.INPUT_GROUP} { display: flex; - background-color: white; + pointer-events: ${({ disabled }) => (disabled ? "none" : "auto")}; + background: ${(props) => + props.disabled ? "var(--wds-color-bg-disabled)" : "white"}; + + span, input, textarea { + background: ${(props) => + props.disabled ? "var(--wds-color-bg-disabled)" : Colors.WHITE}; + color: ${(props) => + props.disabled + ? "var(--wds-color-text-disabled)" + : "var(--wds-color-text)"}; + } > { - - &:first-child:not(input) { - background: ${(props) => - props.disabled ? Colors.GREY_1 : Colors.WHITE}; - } input:not(:first-child) { padding-left: 0rem; z-index: 16; @@ -139,6 +146,7 @@ const InputComponentWrapper = styled((props) => ( ? `${Colors.DANGER_SOLID} !important;` : `${Colors.GREY_3};`; }} + ${(props) => props.numeric && ` @@ -166,13 +174,31 @@ const InputComponentWrapper = styled((props) => ( background: ${Colors.GREY_3}; } + textarea { + background: ${(props) => + props.disabled ? "var(--wds-color-bg-disabled)" : Colors.WHITE}; + color: ${(props) => + props.disabled + ? "var(--wds-color-text-disabled)" + : "var(--wds-color-text)"}; + } + .${Classes.INPUT} { - background: ${Colors.WHITE}; box-shadow: none; border-radius: 0; height: ${(props) => (props.multiline === "true" ? "100%" : "inherit")}; width: 100%; + ::placeholder { + color: ${({ disabled }) => { + if (disabled) { + return "var(--wds-color-text-disabled-light) !important"; + } + + return "var(--wds-color-text-light)"; + }}; + } + ${(props) => props.inputType === "PASSWORD" && ` @@ -182,7 +208,12 @@ const InputComponentWrapper = styled((props) => ( cursor: pointer; .password-input { - color: ${Colors.GREY_6}; + color: + ${ + props.disabled + ? "var(--wds-color-icon-disabled)" + : "var(--wds-color-icon)" + }; justify-content: center; height: 100%; svg { @@ -190,8 +221,7 @@ const InputComponentWrapper = styled((props) => ( height: 20px; } &:hover { - background-color: ${Colors.GREY_2}; - color: ${Colors.GREY_10}; + background-color: var(--wds-color-bg-hover); } } } @@ -203,7 +233,7 @@ const InputComponentWrapper = styled((props) => ( margin: 0; .bp3-tag { background-color: transparent; - color: #5c7080; + color: var(--wds-color-text-danger); } .${Classes.INPUT_ACTION} { @@ -225,6 +255,10 @@ const InputComponentWrapper = styled((props) => ( align-items: center; padding: 0 10px; position: relative; + color: ${({ disabled }) => + disabled + ? "var(--wds-color-icon-disabled)" + : "var(--wds-color-icon)"}; svg { width: 14px; @@ -234,7 +268,8 @@ const InputComponentWrapper = styled((props) => ( &.${Classes.DISABLED} + .bp3-button-group.bp3-vertical { button { - background: ${Colors.GREY_1}; + background: var(--wds-color-bg-disabled); + color: var(--wds-color-icon-disabled) !important; } } } @@ -278,9 +313,9 @@ const StyledNumericInput = styled(NumericInput)` } } span { - color: ${Colors.GREY_6}; + color: var(--wds-color-icon); svg { - width: 14px; + width: 12px; } } } @@ -303,18 +338,41 @@ const TextInputWrapper = styled.div<{ height: 100%; border: 1px solid; overflow: hidden; - border-color: ${({ hasError }) => - hasError ? `${Colors.DANGER_SOLID} !important;` : `${Colors.GREY_3};`} + border-color: ${({ disabled, hasError }) => { + if (disabled) { + return "var(--wds-color-border-disabled)"; + } + + if (hasError) { + return "var(--wds-color-border-danger)"; + } + + return "var(--wds-color-border)"; + }}; border-radius: ${({ borderRadius }) => borderRadius} !important; box-shadow: ${({ boxShadow }) => `${boxShadow}`} !important; min-height: 32px; + &:hover { + border-color: ${({ disabled, hasError }) => { + if (disabled) { + return "var(--wds-color-border-disabled)"; + } + + if (hasError) { + return "var(--wds-color-border-danger-hover)"; + } + + return "var(--wds-color-border-hover)"; + }}; + } + &:focus-within { outline: 0; border-color: ${({ accentColor, hasError }) => hasError ? Colors.DANGER_SOLID : accentColor}; box-shadow: ${({ accentColor, hasError }) => - `0px 0px 0px 3px ${lightenColor( + `0px 0px 0px 2px ${lightenColor( hasError ? Colors.DANGER_SOLID : accentColor, )} !important;`}; } @@ -619,6 +677,7 @@ class BaseInputComponent extends React.Component< boxShadow={this.props.boxShadow} className="text-input-wrapper" compact={compactMode} + disabled={this.props.disabled} hasError={this.props.isInvalid} inputHtmlType={inputHTMLType} labelPosition={labelPosition} diff --git a/app/client/src/widgets/CheckboxWidget/component/index.tsx b/app/client/src/widgets/CheckboxWidget/component/index.tsx index 6e070b171f..b66a71aab8 100644 --- a/app/client/src/widgets/CheckboxWidget/component/index.tsx +++ b/app/client/src/widgets/CheckboxWidget/component/index.tsx @@ -38,7 +38,9 @@ export const CheckboxLabel = styled.div<{ vertical-align: top; text-align: ${({ labelPosition }) => labelPosition.toLowerCase()}; ${({ disabled, labelStyle, labelTextColor, labelTextSize }) => ` - color: ${disabled ? Colors.GREY_8 : labelTextColor || "inherit"}; + color: ${ + disabled ? "var(--wds-color-text-disabled)" : labelTextColor || "inherit" + }; font-size: ${labelTextSize ?? "inherit"}; font-weight: ${labelStyle?.includes(FontStyleTypes.BOLD) ? "bold" : "normal"}; font-style: ${ diff --git a/app/client/src/widgets/CurrencyInputWidget/component/CurrencyCodeDropdown.tsx b/app/client/src/widgets/CurrencyInputWidget/component/CurrencyCodeDropdown.tsx index 570fb215ef..0eb10fea10 100644 --- a/app/client/src/widgets/CurrencyInputWidget/component/CurrencyCodeDropdown.tsx +++ b/app/client/src/widgets/CurrencyInputWidget/component/CurrencyCodeDropdown.tsx @@ -15,27 +15,50 @@ const DropdownTriggerIconWrapper = styled.button` font-size: 14px; line-height: normal; letter-spacing: -0.24px; - color: #090707; - border-right: 1px solid ${Colors.GREY_3}; + color: var(--wds-color-text); + border-right: 1px solid var(--wds-color-border); gap: 0.25rem; padding: 0 0.75rem; height: 100%; margin-right: 0.625rem; + &:disabled { + color: var(--wds-color-text-disabled); + + .dropdown { + background: var(--wds-color-bg-disabled); + + svg { + path { + fill: var(--wds-color-icon-disabled) !important; + } + } + } + } + &:focus { background-color: ${Colors.GREY_1}; + + .dropdown { + background: ${Colors.GREY_1}; + } } .dropdown { svg { - width: 14px; - height: 14px; + width: 16px; + height: 16px; path { - fill: ${Colors.GREY_10} !important; + fill: var(--wds-color-icon) !important; } } } + + &:disabled { + border-right: 1px solid var(--wds-color-border-disabled); + background-color: var(--wds-color-bg-disabled); + } `; export const PopoverStyles = createGlobalStyle<{ @@ -69,16 +92,55 @@ export const PopoverStyles = createGlobalStyle<{ props.portalClassName } .${Classes.INPUT}:active { border: 1px solid ${props.accentColor} !important; - box-shadow: 0px 0px 0px 3px ${lightenColor(props.accentColor)} !important; + box-shadow: 0px 0px 0px 2px ${lightenColor(props.accentColor)} !important; + } + + .${props.portalClassName} .t--dropdown-option:hover { + background-color: var(--wds-color-bg-hover) !important; } - .${props.portalClassName} .t--dropdown-option:hover, .${props.portalClassName} .t--dropdown-option.selected { background-color: ${lightenColor(props.accentColor)} !important; } .${props.portalClassName} .ads-dropdown-options-wrapper { border: 0px solid !important; + box-shadow: none !important; + } + + .${props.portalClassName} .dropdown-search { + margin: 10px !important; + width: calc(100% - 20px); + + input { + border: 1px solid var(--wds-color-border); + padding-left: 36px !important; + padding-right: 10px !important; + } + + .bp3-icon-search { + left: 4px; + right: auto; + } + + .bp3-input-group + div { + display: flex; + height: 100%; + top: 0; + right: 7px; + bottom: 0; + align-items: center; + + svg { + position: relative; + top: 0; + } + } + + input:hover { + background: white; + border: 1px solid var(--wds-color-border-hover); + } } `} `; @@ -145,6 +207,7 @@ interface CurrencyDropdownProps { accentColor?: string; borderRadius?: string; widgetId: string; + isDisabled?: boolean; } export default function CurrencyTypeDropdown(props: CurrencyDropdownProps) { @@ -153,12 +216,13 @@ export default function CurrencyTypeDropdown(props: CurrencyDropdownProps) { const dropdownTrigger = ( {selectedCurrency} {props.allowCurrencyChange && ( - + )} ); @@ -180,6 +244,7 @@ export default function CurrencyTypeDropdown(props: CurrencyDropdownProps) { optionWidth="340px" options={props.options} portalClassName={`country-type-filter-dropdown-${props.widgetId}`} + portalContainer={document.getElementById("art-board") || undefined} searchAutoFocus searchPlaceholder="Search by currency or country" selected={selectedOption} diff --git a/app/client/src/widgets/CurrencyInputWidget/component/index.tsx b/app/client/src/widgets/CurrencyInputWidget/component/index.tsx index c9e9d9dbec..4509df6de0 100644 --- a/app/client/src/widgets/CurrencyInputWidget/component/index.tsx +++ b/app/client/src/widgets/CurrencyInputWidget/component/index.tsx @@ -66,10 +66,9 @@ class CurrencyInputComponent extends React.Component< leftIcon={ props.disabled && "absolute"}; + position: relative; z-index: 2; pointer-events: ${(props) => !props.allowDialCodeChange && "none"}; - ${(props) => (props.disabled ? `background-color: ${Colors.GREY_1};` : "")}; - border-right: 1px solid ${Colors.GREY_3}; + ${(props) => + props.disabled ? `background-color: var(--wds-color-bg-disabled);` : ""}; + border-right: 1px solid var(--wds-color-border); gap: 0.25rem; padding: 0 0.75rem; margin-right: 0.625rem; + &:disabled { + color: var(--wds-color-text-disabled); + + .dropdown { + background: var(--wds-color-bg-disabled); + + svg { + path { + fill: var(--wds-color-icon-disabled) !important; + } + } + } + } + &:focus { background-color: ${Colors.GREY_1}; + + .dropdown { + background: ${Colors.GREY_1}; + } } .dropdown { svg { - width: 14px; - height: 14px; + width: 16px; + height: 16px; path { - fill: ${Colors.GREY_10} !important; + fill: var(--wds-color-icon) !important; } } } + + &:disabled { + border-right: 1px solid var(--wds-color-border-disabled); + background-color: var(--wds-color-bg-disabled); + } `; const FlagWrapper = styled.span` @@ -91,17 +115,56 @@ export const PopoverStyles = createGlobalStyle<{ .${props.portalClassName} .${Classes.INPUT}:focus, .${ props.portalClassName } .${Classes.INPUT}:active { - box-shadow: 0px 0px 0px 3px ${lightenColor(props.accentColor)} !important; + box-shadow: 0px 0px 0px 2px ${lightenColor(props.accentColor)} !important; border: 1px solid ${props.accentColor} !important; } - .${props.portalClassName} .t--dropdown-option:hover, + .${props.portalClassName} .t--dropdown-option:hover { + background-color: var(--wds-color-bg-hover) !important; + } + .${props.portalClassName} .t--dropdown-option.selected { background-color: ${lightenColor(props.accentColor)} !important; } .${props.portalClassName} .ads-dropdown-options-wrapper { border: 0px solid !important; + box-shadow: none !important; + } + + .${props.portalClassName} .dropdown-search { + margin: 10px !important; + width: calc(100% - 20px); + + input { + border: 1px solid var(--wds-color-border); + padding-left: 36px !important; + padding-right: 10px !important; + } + + .bp3-icon-search { + left: 4px; + right: auto; + } + + .bp3-input-group + div { + display: flex; + height: 100%; + top: 0; + right: 7px; + bottom: 0; + align-items: center; + + svg { + position: relative; + top: 0; + } + } + + input:hover { + border: 1px solid var(--wds-color-border-hover); + background: white; + } } `} `; @@ -206,6 +269,7 @@ export default function ISDCodeDropdown(props: ISDCodeDropdownProps) { optionWidth="340px" options={props.options} portalClassName={`country-type-filter-dropdown-${props.widgetId}`} + portalContainer={document.getElementById("art-board") || undefined} searchAutoFocus searchPlaceholder="Search by ISD code or country" selected={props.selected}