diff --git a/app/client/packages/design-system/ads-old/src/SearchComponent/index.tsx b/app/client/packages/design-system/ads-old/src/SearchComponent/index.tsx index ab51942ff46..b8f211c1531 100644 --- a/app/client/packages/design-system/ads-old/src/SearchComponent/index.tsx +++ b/app/client/packages/design-system/ads-old/src/SearchComponent/index.tsx @@ -63,10 +63,11 @@ const SearchInputWrapper = styled(InputGroup)<{ text-overflow: ellipsis; width: 100%; } + input:focus { - border: 1.2px solid var(--ads-old-color-fern-green); - box-sizing: border-box; - width: 100%; + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline); + outline-offset: var(--ads-v2-offset-outline); } input:active { diff --git a/app/client/packages/design-system/ads/src/Button/Button.styles.tsx b/app/client/packages/design-system/ads/src/Button/Button.styles.tsx index 1fd71a2ca84..e6d5e768345 100644 --- a/app/client/packages/design-system/ads/src/Button/Button.styles.tsx +++ b/app/client/packages/design-system/ads/src/Button/Button.styles.tsx @@ -210,6 +210,7 @@ export const StyledButton = styled.button<{ UNSAFE_width?: string; disabled?: boolean; isIconButton?: boolean; + isFocusVisible?: boolean; }>` ${Variables} /* Kind style */ @@ -269,11 +270,14 @@ export const StyledButton = styled.button<{ } } - /* Focus styles */ - &:focus-visible { - outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); - } + ${({ isFocusVisible }) => + isFocusVisible && + css` + :focus-visible { + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; + } + `} } `; diff --git a/app/client/packages/design-system/ads/src/Button/Button.tsx b/app/client/packages/design-system/ads/src/Button/Button.tsx index ca98873225e..4fe30a4265b 100644 --- a/app/client/packages/design-system/ads/src/Button/Button.tsx +++ b/app/client/packages/design-system/ads/src/Button/Button.tsx @@ -1,5 +1,6 @@ import React, { forwardRef } from "react"; import clsx from "classnames"; +import { useFocusRing } from "@react-aria/focus"; import { StyledButton, ButtonContent } from "./Button.styles"; import type { ButtonProps } from "./Button.types"; @@ -16,6 +17,11 @@ import { } from "./Button.constants"; import { Spinner } from "../Spinner"; +// Add this before the Button component definition +const SPINNER_ICON_PROPS = { + className: ButtonLoadingIconClassName, +}; + /** * TODO: * - if both left and right icon is used, disregard left icon and print a warning in the console. @@ -37,21 +43,25 @@ const Button = forwardRef( ...rest } = props; - // disable button when loading - rest.onClick = + // Replace the direct mutation of rest.onClick with this + const handleClick = props.isLoading || props.isDisabled ? undefined : props.onClick; const buttonRef = useDOMRef(ref); + const { focusProps, isFocusVisible } = useFocusRing(); return ( ( {isLoading === true && ( )} diff --git a/app/client/packages/design-system/ads/src/Input/Input.styles.tsx b/app/client/packages/design-system/ads/src/Input/Input.styles.tsx index 5c2bf55e5f1..2b33df83208 100644 --- a/app/client/packages/design-system/ads/src/Input/Input.styles.tsx +++ b/app/client/packages/design-system/ads/src/Input/Input.styles.tsx @@ -164,7 +164,7 @@ export const StyledInput = styled.input<{ renderer === "input" && css` padding-left: calc((var(--input-padding-x) * 2) + var(--icon-size) - 1px); - `}; + `} /* adjust padding end according to icon present or not */ ${({ hasEndIcon, renderer }) => @@ -174,20 +174,13 @@ export const StyledInput = styled.input<{ padding-right: calc( (var(--input-padding-x) * 2) + var(--icon-size) - 1px ); - `}; - - &:focus:enabled:not(:read-only) { - outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); - } + `} &:hover:enabled:not(:read-only) { --input-color-border: var(--ads-v2-colors-control-field-hover-border); } - &:active:enabled:not(:read-only), - &:focus:enabled:not(:read-only) { + &:active:enabled:not(:read-only) { --input-color-border: var(--ads-v2-colors-control-field-active-border); } @@ -203,11 +196,16 @@ export const StyledInput = styled.input<{ --input-color-border: var(--ads-v2-colors-control-field-error-border); } - &:active:enabled:not(:read-only), - &:focus:enabled:not(:read-only) { + &:active:enabled:not(:read-only) { --input-color-border: var(--ads-v2-colors-control-field-error-border); } } + + &:focus { + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; + } `; export const Description = styled(Text)` diff --git a/app/client/packages/design-system/ads/src/Input/Input.tsx b/app/client/packages/design-system/ads/src/Input/Input.tsx index c196c17e165..c3c57afda23 100644 --- a/app/client/packages/design-system/ads/src/Input/Input.tsx +++ b/app/client/packages/design-system/ads/src/Input/Input.tsx @@ -1,5 +1,4 @@ -import React, { forwardRef } from "react"; -import { useFocusRing } from "@react-aria/focus"; +import React, { forwardRef, useCallback } from "react"; import { useTextField } from "@react-aria/textfield"; import clsx from "classnames"; @@ -55,7 +54,7 @@ const Input = forwardRef( const { descriptionProps, errorMessageProps, inputProps, labelProps } = // @ts-expect-error fix this the next time the file is edited useTextField(props, inputRef); - const { focusProps, isFocusVisible } = useFocusRing(); + const { className: startIconClassName, onClick: startIconOnClick, @@ -67,9 +66,12 @@ const Input = forwardRef( ...restOfEndIconProps } = endIconProps || {}; - const handleOnChange = (event: React.ChangeEvent) => { - onChange?.(event.target.value); - }; + const handleOnChange = useCallback( + (event: React.ChangeEvent) => { + onChange?.(event.target.value); + }, + [onChange], + ); isValid = isValid === undefined ? !errorMessage : isValid; @@ -116,7 +118,6 @@ const Input = forwardRef( ( hasEndIcon={!!endIcon} hasStartIcon={!!startIcon} inputSize={size} - isFocusVisible={isFocusVisible} onChange={handleOnChange} readOnly={isReadOnly} ref={inputRef} diff --git a/app/client/packages/design-system/ads/src/Link/Link.styles.tsx b/app/client/packages/design-system/ads/src/Link/Link.styles.tsx index 357316fd4d7..8c853d0e4ba 100644 --- a/app/client/packages/design-system/ads/src/Link/Link.styles.tsx +++ b/app/client/packages/design-system/ads/src/Link/Link.styles.tsx @@ -91,8 +91,8 @@ export const Styles = css<{ kind?: LinkKind }>` :focus-visible { outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; border-radius: var(--ads-v2-border-radius); } `; diff --git a/app/client/packages/design-system/ads/src/SegmentedControl/SegmentedControl.styles.tsx b/app/client/packages/design-system/ads/src/SegmentedControl/SegmentedControl.styles.tsx index df71f94da91..ce6db61c553 100644 --- a/app/client/packages/design-system/ads/src/SegmentedControl/SegmentedControl.styles.tsx +++ b/app/client/packages/design-system/ads/src/SegmentedControl/SegmentedControl.styles.tsx @@ -67,8 +67,8 @@ export const StyledControlContainer = styled.div` &:focus-visible { outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; } &[data-disabled="true"] { diff --git a/app/client/packages/design-system/ads/src/Select/styles.css b/app/client/packages/design-system/ads/src/Select/styles.css index cc67992917a..5df37c481ce 100644 --- a/app/client/packages/design-system/ads/src/Select/styles.css +++ b/app/client/packages/design-system/ads/src/Select/styles.css @@ -1,7 +1,9 @@ .ads-v2-select { --select-color-border: var(--ads-v2-colors-control-field-default-border); - --select-padding-x: var(--ads-v2-spaces-2); /* padding left and right */ - --select-padding-y: var(--ads-v2-spaces-2); /* padding top and bottom */ + --select-padding-x: var(--ads-v2-spaces-2); + /* padding left and right */ + --select-padding-y: var(--ads-v2-spaces-2); + /* padding top and bottom */ --select-font-size: var(--ads-v2-font-size-2); --select-height: 24px; --select-search-input-padding-right: 0; @@ -51,7 +53,6 @@ .ads-v2-select.rc-select-focused { outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); outline-offset: var(--ads-v2-offset-outline); - --select-color-border: var(--ads-v2-colors-control-field-active-border); } /* Error */ @@ -87,6 +88,7 @@ /* padding x + icon size + gap */ --select-search-input-padding-right: calc(var(--select-padding-x) + 16px); } + .ads-v2-select.rc-select-allow-clear.rc-select-show-arrow.rc-select-selection-search-input, .ads-v2-select.rc-select-allow-clear.rc-select-show-arrow .rc-select-selection-overflow { @@ -113,6 +115,10 @@ overflow: hidden; } +.ads-v2-select.rc-select-focused > .rc-select-selector { + border-color: transparent; +} + /* Placeholder */ .ads-v2-select > .rc-select-selector > .rc-select-selection-placeholder, .ads-v2-select > .rc-select-selector > .rc-select-selection-item { diff --git a/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx b/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx index 2b0358ffeee..f4459720fc5 100644 --- a/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx +++ b/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx @@ -72,8 +72,9 @@ export const StyledSwitchInput = styled.input<{ ${({ isFocusVisible }) => isFocusVisible && ` - outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; `} &:hover { diff --git a/app/client/packages/design-system/ads/src/Tab/Tab.styles.tsx b/app/client/packages/design-system/ads/src/Tab/Tab.styles.tsx index 082c272ceba..1abc54866a9 100644 --- a/app/client/packages/design-system/ads/src/Tab/Tab.styles.tsx +++ b/app/client/packages/design-system/ads/src/Tab/Tab.styles.tsx @@ -88,7 +88,7 @@ export const StyledTab = styled(RadixTabs.TabsTrigger)` &:focus-visible { --tab-color: var(--ads-v2-colors-content-label-default-fg); outline: var(--ads-v2-border-width-outline) solid - var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; } `; diff --git a/app/client/packages/design-system/ads/src/Text/Text.styles.tsx b/app/client/packages/design-system/ads/src/Text/Text.styles.tsx index 55f278fa7b1..3610ce324ec 100644 --- a/app/client/packages/design-system/ads/src/Text/Text.styles.tsx +++ b/app/client/packages/design-system/ads/src/Text/Text.styles.tsx @@ -201,8 +201,13 @@ export const StyledEditableInput = styled.input` border-color: var(--ads-v2-colors-control-field-hover-border); } - &:focus, &:active { border-color: var(--ads-v2-colors-control-field-active-border); } + + &:focus-visible { + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline); + outline-offset: var(--ads-v2-offset-outline); + } `; diff --git a/app/client/packages/design-system/ads/src/__theme__/default/index.css b/app/client/packages/design-system/ads/src/__theme__/default/index.css index ad6c149f68c..8ade0c331b8 100644 --- a/app/client/packages/design-system/ads/src/__theme__/default/index.css +++ b/app/client/packages/design-system/ads/src/__theme__/default/index.css @@ -239,9 +239,9 @@ /* --ads-v2-color-outline: var(--ads-v2-color-blue-300); --ads-v2-border-width-outline: 2px; */ /* TODO: fix focus issue across the platform */ - --ads-v2-color-outline: transparent; - --ads-v2-border-width-outline: 0; - --ads-v2-offset-outline: 0; + --ads-v2-color-outline: var(--ads-v2-color-blue-300); + --ads-v2-border-width-outline: 2px; + --ads-v2-offset-outline: -2px; /** * ===========================================* @@ -251,17 +251,22 @@ --ads-v2-opacity-disabled: 0.6; } +:focus { + outline: none !important; +} + /* react-aria useFocusRing helper class*/ .ads-v2-focus-ring { - outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); - outline-offset: var(--ads-v2-offset-outline); + outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; } /* Placeholder color */ ::placeholder { /* This needs to be important to override the placeholder color on main repo */ color: var(--ads-v2-colors-control-placeholder-default-fg) !important; - opacity: 1; /* Firefox */ + opacity: 1; + /* Firefox */ } :-ms-input-placeholder { diff --git a/app/client/src/components/editorComponents/CodeEditor/index.tsx b/app/client/src/components/editorComponents/CodeEditor/index.tsx index 8c9027dc647..21610927e3c 100644 --- a/app/client/src/components/editorComponents/CodeEditor/index.tsx +++ b/app/client/src/components/editorComponents/CodeEditor/index.tsx @@ -1794,6 +1794,7 @@ class CodeEditor extends Component { onMouseOver={this.handleMouseMove} ref={this.editorWrapperRef} removeHoverAndFocusStyle={this.props?.removeHoverAndFocusStyle} + showFocusVisible={!this.props.isJSObject} size={size} > {this.state.peekOverlayProps && ( diff --git a/app/client/src/components/editorComponents/CodeEditor/styledComponents.ts b/app/client/src/components/editorComponents/CodeEditor/styledComponents.ts index 5c4cd413679..c26b3eec794 100644 --- a/app/client/src/components/editorComponents/CodeEditor/styledComponents.ts +++ b/app/client/src/components/editorComponents/CodeEditor/styledComponents.ts @@ -54,6 +54,7 @@ export const EditorWrapper = styled.div<{ AIEnabled?: boolean; mode: string; maxHeight?: string | number; + showFocusVisible?: boolean; }>` // Bottom border was getting clipped .CodeMirror.cm-s-duotone-light.CodeMirror-wrap { @@ -83,6 +84,17 @@ export const EditorWrapper = styled.div<{ text-transform: none; && { + ${(props) => + props.showFocusVisible && + ` + .CodeMirror-focused { + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline) !important; + outline-offset: var(--ads-v2-offset-outline) !important; + z-index: 1 !important; + } + `} + .CodeMirror-cursor { border-right: none; border-left-width: 2px; @@ -390,12 +402,11 @@ export const EditorWrapper = styled.div<{ } } - &:focus { + &:focus-visible { .CodeMirror.cm-s-duotone-light { - border-color: ${(props) => - props.borderLess - ? "none" - : "var(--ads-v2-color-border-emphasis-plus)"}; + outline: var(--ads-v2-border-width-outline) solid + var(--ads-v2-color-outline); + outline-offset: var(--ads-v2-offset-outline); } } diff --git a/app/client/src/components/propertyControls/ColorPickerComponentV2.tsx b/app/client/src/components/propertyControls/ColorPickerComponentV2.tsx index f275b74469f..c80ad0ee8ad 100644 --- a/app/client/src/components/propertyControls/ColorPickerComponentV2.tsx +++ b/app/client/src/components/propertyControls/ColorPickerComponentV2.tsx @@ -95,14 +95,13 @@ export const StyledInputGroup = styled(InputGroup)<{ props.theme.colors.propertyPane.multiDropdownBoxHoverBg}; color: ${(props) => props.theme.colors.propertyPane.label}; - &:focus { + &:focus-visible { outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); outline-offset: var(--ads-v2-offset-outline); } - &:hover, - &:focus { + &:hover { border-color: ${({ $isValid }) => $isValid ? "var(--ads-v2-color-border-emphasis)" diff --git a/app/client/src/components/propertyControls/IconSelectControl.tsx b/app/client/src/components/propertyControls/IconSelectControl.tsx index d968d0dc61d..e4d8379ddba 100644 --- a/app/client/src/components/propertyControls/IconSelectControl.tsx +++ b/app/client/src/components/propertyControls/IconSelectControl.tsx @@ -52,10 +52,10 @@ const StyledButton = styled(Button)` border: 1px solid var(--ads-v2-color-border-emphasis); } - &:focus { + &:focus-visible { outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); - border: 1px solid var(--ads-v2-color-border-emphasis); + outline-offset: var(--ads-v2-offset-outline); } `; diff --git a/app/client/src/components/propertyControls/IconSelectControlV2.tsx b/app/client/src/components/propertyControls/IconSelectControlV2.tsx index bdcdcc2e0b1..4d51f1de720 100644 --- a/app/client/src/components/propertyControls/IconSelectControlV2.tsx +++ b/app/client/src/components/propertyControls/IconSelectControlV2.tsx @@ -53,10 +53,10 @@ const StyledButton = styled(Button)` border: 1px solid var(--ads-v2-color-border-emphasis); } - &:focus { + &:focus-visible { outline: var(--ads-v2-border-width-outline) solid var(--ads-v2-color-outline); - border: 1px solid var(--ads-v2-color-border-emphasis); + outline-offset: var(--ads-v2-offset-outline); } > span.bp3-button-text { diff --git a/app/client/src/index.css b/app/client/src/index.css index 9758abf54e0..871aa36fb5b 100755 --- a/app/client/src/index.css +++ b/app/client/src/index.css @@ -22,23 +22,6 @@ body.dragging * { cursor: grabbing !important; } -/** - Disable outline completely from all components -*/ -:focus, -:focus-visible { - outline: none !important; - outline-offset: 0 !important; -} - -/** - Disable outline for adsv2 select component -*/ -.ads-v2-select.rc-select-focused { - outline: none !important; - outline-offset: 0 !important; -} - #root.overlay { opacity: 0; pointer-events: none;