From 39c849754a8454a7f0f45a21b7b5f45e716e05e7 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Fri, 9 Aug 2024 16:08:06 -0700 Subject: [PATCH 01/21] [docs] Clean up EuiFormControlLayoutDelimited example - each input can use `controlOnly` to reduce number of layout wrappers rendered + remove direct `euiFieldNumber` className --- .../form_control_layout_range.tsx | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/eui/src-docs/src/views/form_controls/form_control_layout_range.tsx b/packages/eui/src-docs/src/views/form_controls/form_control_layout_range.tsx index 8c9e4c85dfa..08301eb43f7 100644 --- a/packages/eui/src-docs/src/views/form_controls/form_control_layout_range.tsx +++ b/packages/eui/src-docs/src/views/form_controls/form_control_layout_range.tsx @@ -19,15 +19,15 @@ export default () => ( fullWidth startControl={ } endControl={ } @@ -36,15 +36,15 @@ export default () => ( } endControl={ } @@ -54,15 +54,15 @@ export default () => ( append={px} startControl={ } endControl={ } @@ -73,14 +73,14 @@ export default () => ( startControl={ } endControl={ } @@ -91,15 +91,15 @@ export default () => ( isLoading startControl={ } endControl={ } @@ -109,15 +109,15 @@ export default () => ( isLoading startControl={ } endControl={ } @@ -127,15 +127,15 @@ export default () => ( compressed startControl={ } endControl={ } @@ -145,16 +145,16 @@ export default () => ( prepend={Add} startControl={ } delimiter="+" endControl={ } @@ -164,16 +164,16 @@ export default () => ( prepend={Merge} startControl={ } delimiter={} endControl={ } @@ -184,16 +184,16 @@ export default () => ( prepend={Read only} startControl={ } endControl={ @@ -205,16 +205,16 @@ export default () => ( prepend={Disabled} startControl={ } endControl={ From 18d507f5cbfa763e383c95c483bed11067c11ba5 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sat, 10 Aug 2024 17:02:45 -0700 Subject: [PATCH 02/21] DRY out repeated border/border-radius styles by adding new prop - allows us to write us less repeated CSS --- ...orm_control_layout_delimited.test.tsx.snap | 12 +++--- .../_form_control_layout_delimited.scss | 12 ------ .../form_control_layout.tsx | 10 +++-- .../form_control_layout_delimited.tsx | 7 +++- .../_form_control_layout_delimited.scss | 42 ------------------- 5 files changed, 19 insertions(+), 64 deletions(-) diff --git a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap index ad93640f2b3..2a6eff29706 100644 --- a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap +++ b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap @@ -3,11 +3,11 @@ exports[`EuiFormControlLayoutDelimited is rendered 1`] = `
.euiFormControlLayout__childrenWrapper { display: flex; align-items: center; @@ -12,12 +6,6 @@ background-color: $euiFormBackgroundColor; } - // Target when the euiFormControlLayout is compressed without specifying the full class name in case it ever changes - &[class*='-compressed'] { - @include euiFormControlDefaultShadow($borderOnly: true); - border-radius: $euiBorderRadius / 2; - } - // Target when the euiFormControlLayout is fullWidth without specifying the full class name in case it ever changes &[class*='-fullWidth'] .euiFormControlLayout__childrenWrapper, &[class*='-fullWidth'] .euiFormControlLayout__childrenWrapper > *:not(.euiFormControlLayoutDelimited__delimiter):not(.euiFormControlLayoutIcons) { diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout.tsx index a1797de2c90..cef0ed3e1ee 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout.tsx @@ -77,7 +77,10 @@ export type EuiFormControlLayoutProps = CommonProps & }; export const EuiFormControlLayout: FunctionComponent< - EuiFormControlLayoutProps + EuiFormControlLayoutProps & { + // Internal prop used by EuiFormControlLayoutDelimited + isDelimited?: boolean; + } > = (props) => { const { defaultFullWidth } = useFormContext(); const { @@ -95,16 +98,17 @@ export const EuiFormControlLayout: FunctionComponent< compressed, prepend, append, + isDelimited, fullWidth = defaultFullWidth, ...rest } = props; - const isGroup = !!(prepend || append); + const isGroup = !!(prepend || append || isDelimited); const classes = classNames( 'euiFormControlLayout', { - 'euiFormControlLayout--group': isGroup, + 'euiFormControlLayout--group': isGroup && !isDelimited, 'euiFormControlLayout-isDisabled': isDisabled, 'euiFormControlLayout-readOnly': readOnly, }, diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx index f6c5919976c..1d04e6181b2 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx @@ -52,7 +52,12 @@ export const EuiFormControlLayoutDelimited: FunctionComponent< }); return ( - + {addClassesToControl(startControl)} Date: Sat, 10 Aug 2024 17:13:36 -0700 Subject: [PATCH 03/21] Set up basic delimited styles - delimited is just there for classNames, group styles already takes care of it. disabled/readonly can just inherit form styles --- ...orm_control_layout_delimited.test.tsx.snap | 6 ++--- .../_form_control_layout_delimited.scss | 18 ------------- .../form_control_layout_delimited.styles.ts | 26 +++++++++++++++++++ .../form_control_layout_delimited.tsx | 10 +++++++ 4 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts diff --git a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap index 2a6eff29706..43248f02ba2 100644 --- a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap +++ b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap @@ -3,7 +3,7 @@ exports[`EuiFormControlLayoutDelimited is rendered 1`] = `
{ + return { + // Appended onto existing `euiFormControlLayout` styles + delimited: css``, + disabled: css(euiFormControlDisabledStyles(euiThemeContext)), + readOnly: css(euiFormControlReadOnlyStyles(euiThemeContext)), + }; +}; diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx index 1d04e6181b2..d33d495aa30 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx @@ -14,6 +14,7 @@ import React, { } from 'react'; import classNames from 'classnames'; +import { useEuiMemoizedStyles } from '../../../services'; import { useEuiI18n } from '../../i18n'; import { EuiIcon } from '../../icon'; import { EuiText } from '../../text'; @@ -22,6 +23,7 @@ import { EuiFormControlLayout, EuiFormControlLayoutProps, } from './form_control_layout'; +import { euiFormControlLayoutDelimitedStyles } from './form_control_layout_delimited.styles'; export type EuiFormControlLayoutDelimitedProps = Partial & { @@ -51,9 +53,17 @@ export const EuiFormControlLayoutDelimited: FunctionComponent< 'euiFormControlLayoutDelimited--isInvalid': showInvalidState, }); + const styles = useEuiMemoizedStyles(euiFormControlLayoutDelimitedStyles); + const cssStyles = [ + styles.delimited, + rest.isDisabled && styles.disabled, + rest.readOnly && styles.readOnly, + ]; + return ( Date: Sat, 10 Aug 2024 17:27:26 -0700 Subject: [PATCH 04/21] Allowing passing styles directly to `.euiFormControlLayout__childrenWrapper` --- .../form_control_layout_delimited.test.tsx.snap | 6 +++--- .../_form_control_layout_delimited.scss | 7 ------- .../form_control_layout.test.tsx | 4 +++- .../form_control_layout/form_control_layout.tsx | 14 ++++++++++++-- .../form_control_layout_delimited.styles.ts | 9 +++++++++ .../form_control_layout_delimited.tsx | 4 ++++ 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap index 43248f02ba2..7d1131e1d0b 100644 --- a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap +++ b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap @@ -7,7 +7,7 @@ exports[`EuiFormControlLayoutDelimited is rendered 1`] = ` data-test-subj="test subject string" >
.euiFormControlLayout__childrenWrapper { - display: flex; - align-items: center; - width: 100%; - background-color: $euiFormBackgroundColor; - } - // Target when the euiFormControlLayout is fullWidth without specifying the full class name in case it ever changes &[class*='-fullWidth'] .euiFormControlLayout__childrenWrapper, &[class*='-fullWidth'] .euiFormControlLayout__childrenWrapper > *:not(.euiFormControlLayoutDelimited__delimiter):not(.euiFormControlLayoutIcons) { diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout.test.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout.test.tsx index ab0cf5bc8ac..2328d30bcc6 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout.test.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout.test.tsx @@ -22,7 +22,9 @@ jest.mock('../../', () => ({ })); describe('EuiFormControlLayout', () => { - shouldRenderCustomStyles(); + shouldRenderCustomStyles(, { + childProps: ['wrapperProps'], + }); test('is rendered', () => { const { container } = render( diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout.tsx index cef0ed3e1ee..bfb4b97bdcd 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout.tsx @@ -74,6 +74,10 @@ export type EuiFormControlLayoutProps = CommonProps & * Connects the prepend and append labels to the input */ inputId?: string; + /** + * Allows passing optional additional props to `.euiFormControlLayout__childrenWrapper` + */ + wrapperProps?: CommonProps & HTMLAttributes; }; export const EuiFormControlLayout: FunctionComponent< @@ -99,6 +103,7 @@ export const EuiFormControlLayout: FunctionComponent< prepend, append, isDelimited, + wrapperProps, fullWidth = defaultFullWidth, ...rest } = props; @@ -134,6 +139,7 @@ export const EuiFormControlLayout: FunctionComponent< isGroup && styles.children.inGroup, isGroup && !append && styles.children.prependOnly, isGroup && !prepend && styles.children.appendOnly, + wrapperProps?.css, ]; const hasDropdownIcon = !readOnly && !isDisabled && isDropdown; @@ -163,9 +169,13 @@ export const EuiFormControlLayout: FunctionComponent< compressed={compressed} />
{hasLeftIcon && ( Date: Sat, 10 Aug 2024 17:30:44 -0700 Subject: [PATCH 05/21] Set up invalid styles - underline needs to be on the children wrapper and not on the full parent - extend `euiFormControlDefaultShadow` to allow setting either just the box-shadow or the background-gradient --- packages/eui/src/components/form/form.styles.ts | 7 +++++-- .../_form_control_layout_delimited.scss | 4 ---- .../form_control_layout_delimited.styles.ts | 4 ++++ .../form_control_layout/form_control_layout_delimited.tsx | 1 + 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/eui/src/components/form/form.styles.ts b/packages/eui/src/components/form/form.styles.ts index 510cb24761b..08efab65392 100644 --- a/packages/eui/src/components/form/form.styles.ts +++ b/packages/eui/src/components/form/form.styles.ts @@ -231,7 +231,10 @@ export const euiFormControlText = (euiThemeContext: UseEuiTheme) => { export const euiFormControlDefaultShadow = ( euiThemeContext: UseEuiTheme, - { withBackground = true }: { withBackground?: boolean } = {} + { + withBorder = true, + withBackground = true, + }: { withBorder?: boolean; withBackground?: boolean } = {} ) => { const { euiTheme } = euiThemeContext; const form = euiFormVariables(euiThemeContext); @@ -261,7 +264,7 @@ export const euiFormControlDefaultShadow = ( }`; return ` - ${border} + ${withBorder ? border : ''} ${withBackground ? backgroundGradient : ''} `; }; diff --git a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss index 50dd17126cd..f632a41e2c4 100644 --- a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss +++ b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss @@ -5,10 +5,6 @@ width: 100%; max-width: none; } - - &--isInvalid .euiFormControlLayout__childrenWrapper { - @include euiFormControlInvalidStyle; - } } .euiFormControlLayoutDelimited__input { diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts index e28afaaf79a..34ab1deb634 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts @@ -30,6 +30,10 @@ export const euiFormControlLayoutDelimitedStyles = ( delimited: css` display: flex; `, + invalid: css( + euiFormControlDefaultShadow(euiThemeContext, { withBorder: false }), + euiFormControlInvalidStyles(euiThemeContext) + ), }, }; }; diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx index 4a185a1809b..788d207e9f2 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx @@ -61,6 +61,7 @@ export const EuiFormControlLayoutDelimited: FunctionComponent< ]; const wrapperStyles = [ styles.childrenWrapper.delimited, + showInvalidState && styles.childrenWrapper.invalid, ]; return ( From 43edc3e4d6ac051eb4f4fbc6011a5fdc6f7578e6 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sat, 10 Aug 2024 17:38:12 -0700 Subject: [PATCH 06/21] Replace fullWidth CSS with React context - JS context is generally more reliable than wildcard CSS, and consumers should generally prefer to use EUI components rather than not (or set their own styles if they're using raw HTML inputs) + fix EuiFormControlLayoutDelimited not inheriting fullWidth from form context --- .../_form_control_layout_delimited.scss | 9 ------ .../form_control_layout_delimited.test.tsx | 18 ++++++++++++ .../form_control_layout_delimited.tsx | 28 ++++++++++++++----- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss index f632a41e2c4..926701c815f 100644 --- a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss +++ b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss @@ -1,12 +1,3 @@ -.euiFormControlLayoutDelimited { - // Target when the euiFormControlLayout is fullWidth without specifying the full class name in case it ever changes - &[class*='-fullWidth'] .euiFormControlLayout__childrenWrapper, - &[class*='-fullWidth'] .euiFormControlLayout__childrenWrapper > *:not(.euiFormControlLayoutDelimited__delimiter):not(.euiFormControlLayoutIcons) { - width: 100%; - max-width: none; - } -} - .euiFormControlLayoutDelimited__input { // stylelint-disable declaration-no-important box-shadow: none !important; diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.test.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.test.tsx index 9d67f323582..b69cabca5d1 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.test.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.test.tsx @@ -57,4 +57,22 @@ describe('EuiFormControlLayoutDelimited', () => { }); }); }); + + describe('inherits', () => { + test('fullWidth from ', () => { + const { baseElement } = render( + + start} + endControl={end} + /> + + ); + + const layout = baseElement.querySelector( + '.euiFormControlLayoutDelimited' + ); + expect(layout!.className).toContain('fullWidth'); + }); + }); }); diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx index 788d207e9f2..cdf8902d6c3 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx @@ -19,6 +19,7 @@ import { useEuiI18n } from '../../i18n'; import { EuiIcon } from '../../icon'; import { EuiText } from '../../text'; +import { FormContext, useFormContext } from '../eui_form_context'; import { EuiFormControlLayout, EuiFormControlLayoutProps, @@ -45,7 +46,17 @@ export type EuiFormControlLayoutDelimitedProps = export const EuiFormControlLayoutDelimited: FunctionComponent< EuiFormControlLayoutDelimitedProps -> = ({ startControl, endControl, delimiter, className, ...rest }) => { +> = ({ + startControl, + endControl, + delimiter, + className, + fullWidth: _fullWidth, + ...rest +}) => { + const { defaultFullWidth } = useFormContext(); + const fullWidth = _fullWidth ?? defaultFullWidth; + const { isInvalid, isDisabled, readOnly } = rest; const showInvalidState = isInvalid && !isDisabled && !readOnly; @@ -71,14 +82,17 @@ export const EuiFormControlLayoutDelimited: FunctionComponent< wrapperProps={{ css: wrapperStyles }} className={classes} iconsPosition="static" + fullWidth={fullWidth} {...rest} > - {addClassesToControl(startControl)} - - {addClassesToControl(endControl)} + + {addClassesToControl(startControl)} + + {addClassesToControl(endControl)} + ); }; From 800ab9bda922395bf605da5b3b707b289977367c Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sat, 10 Aug 2024 17:54:55 -0700 Subject: [PATCH 07/21] Convert delimiter styles to Emotion - doesn't have theme tokens and can just be a static const --- .../form_control_layout_delimited.test.tsx.snap | 6 +++--- .../_form_control_layout_delimited.scss | 8 -------- .../form_control_layout_delimited.styles.ts | 9 +++++++++ .../form_control_layout_delimited.tsx | 6 +++++- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap index 7d1131e1d0b..c7ef985313e 100644 --- a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap +++ b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap @@ -15,7 +15,7 @@ exports[`EuiFormControlLayoutDelimited is rendered 1`] = ` start
+
diff --git a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss index 926701c815f..2377c01db11 100644 --- a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss +++ b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss @@ -7,11 +7,3 @@ height: 100%; min-width: 0; // Fixes FF } - -.euiFormControlLayoutDelimited__delimiter { - align-self: stretch; - flex-grow: 0; - display: flex; - align-items: center; - line-height: 1; // Override EuiText line-height -} diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts index 34ab1deb634..a7baba8d1bc 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts @@ -37,3 +37,12 @@ export const euiFormControlLayoutDelimitedStyles = ( }, }; }; + +export const euiFormControlLayoutDelimited__delimiter = css` + align-self: stretch; + flex-grow: 0; + display: flex; + align-items: center; + line-height: 1; /* Override EuiText line-height */ +`; + diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx index cdf8902d6c3..96486501db3 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx @@ -24,7 +24,10 @@ import { EuiFormControlLayout, EuiFormControlLayoutProps, } from './form_control_layout'; -import { euiFormControlLayoutDelimitedStyles } from './form_control_layout_delimited.styles'; +import { + euiFormControlLayoutDelimitedStyles, + euiFormControlLayoutDelimited__delimiter, +} from './form_control_layout_delimited.styles'; export type EuiFormControlLayoutDelimitedProps = Partial & { @@ -120,6 +123,7 @@ const EuiFormControlDelimiter = ({ return ( Date: Sat, 10 Aug 2024 18:14:47 -0700 Subject: [PATCH 08/21] Convert `.euiFormControlLayoutDelimited__input` styles + Fix `cloneElementWithCss()` throwing an error if used twice without a `key` - remove unnecessary `!important`s - no longer needed with flattened Emotion styles - remove unnecessary `min-width: 0` (no longer an issue on Firefox?) --- .../form_control_layout_delimited.test.tsx.snap | 12 ++++++------ .../_form_control_layout_delimited.scss | 9 --------- .../form_control_layout_delimited.styles.ts | 7 +++++++ .../form_control_layout_delimited.tsx | 13 +++++-------- .../src/services/emotion/clone_element.test.tsx | 16 ++++++++++++++++ .../eui/src/services/emotion/clone_element.tsx | 2 +- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap index c7ef985313e..141bb81bc41 100644 --- a/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap +++ b/packages/eui/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap @@ -10,7 +10,7 @@ exports[`EuiFormControlLayoutDelimited is rendered 1`] = ` class="euiFormControlLayout__childrenWrapper emotion-euiFormControlLayout__childrenWrapper-inGroup-prependOnly-appendOnly-delimited" > start @@ -24,7 +24,7 @@ exports[`EuiFormControlLayoutDelimited is rendered 1`] = `
end @@ -40,7 +40,7 @@ exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a node 1`] class="euiFormControlLayout__childrenWrapper emotion-euiFormControlLayout__childrenWrapper-inGroup-prependOnly-appendOnly-delimited" > start @@ -52,7 +52,7 @@ exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a node 1`] />
end @@ -68,7 +68,7 @@ exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a string 1 class="euiFormControlLayout__childrenWrapper emotion-euiFormControlLayout__childrenWrapper-inGroup-prependOnly-appendOnly-delimited" > start @@ -78,7 +78,7 @@ exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a string 1 +
end diff --git a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss index 2377c01db11..e69de29bb2d 100644 --- a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss +++ b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss @@ -1,9 +0,0 @@ -.euiFormControlLayoutDelimited__input { - // stylelint-disable declaration-no-important - box-shadow: none !important; - border-radius: 0 !important; - // stylelint-enable declaration-no-important - text-align: center; - height: 100%; - min-width: 0; // Fixes FF -} diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts index a7baba8d1bc..56ab6ef399f 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.styles.ts @@ -9,6 +9,7 @@ import { css } from '@emotion/react'; import { UseEuiTheme } from '../../../services'; +import { logicalCSS } from '../../../global_styling'; import { euiFormControlDisabledStyles, euiFormControlReadOnlyStyles, @@ -46,3 +47,9 @@ export const euiFormControlLayoutDelimited__delimiter = css` line-height: 1; /* Override EuiText line-height */ `; +export const euiFormControlLayoutDelimited__input = css` + box-shadow: none; + border-radius: 0; + text-align: center; + ${logicalCSS('height', '100%')} +`; diff --git a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx index 96486501db3..3247bb3a396 100644 --- a/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx +++ b/packages/eui/src/components/form/form_control_layout/form_control_layout_delimited.tsx @@ -6,15 +6,10 @@ * Side Public License, v 1. */ -import React, { - FunctionComponent, - ReactElement, - cloneElement, - ReactNode, -} from 'react'; +import React, { FunctionComponent, ReactElement, ReactNode } from 'react'; import classNames from 'classnames'; -import { useEuiMemoizedStyles } from '../../../services'; +import { useEuiMemoizedStyles, cloneElementWithCss } from '../../../services'; import { useEuiI18n } from '../../i18n'; import { EuiIcon } from '../../icon'; import { EuiText } from '../../text'; @@ -27,6 +22,7 @@ import { import { euiFormControlLayoutDelimitedStyles, euiFormControlLayoutDelimited__delimiter, + euiFormControlLayoutDelimited__input, } from './form_control_layout_delimited.styles'; export type EuiFormControlLayoutDelimitedProps = @@ -101,7 +97,8 @@ export const EuiFormControlLayoutDelimited: FunctionComponent< }; const addClassesToControl = (control: ReactElement) => { - return cloneElement(control, { + return cloneElementWithCss(control, { + css: euiFormControlLayoutDelimited__input, className: classNames( control.props.className, 'euiFormControlLayoutDelimited__input' diff --git a/packages/eui/src/services/emotion/clone_element.test.tsx b/packages/eui/src/services/emotion/clone_element.test.tsx index c1509d865e0..9b00cd67d0c 100644 --- a/packages/eui/src/services/emotion/clone_element.test.tsx +++ b/packages/eui/src/services/emotion/clone_element.test.tsx @@ -101,4 +101,20 @@ describe('cloneElementWithCss', () => { `); expect(container.firstChild).not.toHaveStyleRule('color', 'red'); }); + + it('does not error with or without `key` props', () => { + const cloned =
; + const KeyTest = () => ( + <> + {cloneElementWithCss(cloned, { css: { color: 'red' } })} + {cloneElementWithCss(cloned, { css: { color: 'blue' } })} + {cloneElementWithCss(cloned, { key: 'someKey' })} + + ); + const { container } = render(); + + expect(container.children[0]).toHaveStyleRule('color', 'red'); + expect(container.children[1]).toHaveStyleRule('color', 'blue'); + expect(container.children[2]).not.toHaveStyleRule('color'); + }); }); diff --git a/packages/eui/src/services/emotion/clone_element.tsx b/packages/eui/src/services/emotion/clone_element.tsx index a090e5d4713..56be0a060c6 100644 --- a/packages/eui/src/services/emotion/clone_element.tsx +++ b/packages/eui/src/services/emotion/clone_element.tsx @@ -22,7 +22,7 @@ export const cloneElementWithCss = ( element.props.__EMOTION_TYPE_PLEASE_DO_NOT_USE__ || element.type; // EMOTION_TYPE handles non-React elements (native JSX/HTML nodes) const clonedProps = { - key: element.key, + ...(element.key ? { key: element.key } : {}), ref: element.ref, ...element.props, ...props, From 2091371c1ca2f0c04bb2fd50c191db1b10b15c98 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sat, 10 Aug 2024 18:15:27 -0700 Subject: [PATCH 09/21] Delete Sass files --- .../form/form_control_layout/_form_control_layout_delimited.scss | 0 packages/eui/src/components/form/form_control_layout/_index.scss | 1 - .../amsterdam/overrides/_form_control_layout_delimited.scss | 0 packages/eui/src/themes/amsterdam/overrides/_index.scss | 1 - 4 files changed, 2 deletions(-) delete mode 100644 packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss delete mode 100644 packages/eui/src/themes/amsterdam/overrides/_form_control_layout_delimited.scss diff --git a/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/packages/eui/src/components/form/form_control_layout/_form_control_layout_delimited.scss deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/eui/src/components/form/form_control_layout/_index.scss b/packages/eui/src/components/form/form_control_layout/_index.scss index f5bad883226..df8eb6e7a27 100644 --- a/packages/eui/src/components/form/form_control_layout/_index.scss +++ b/packages/eui/src/components/form/form_control_layout/_index.scss @@ -1,4 +1,3 @@ -@import 'form_control_layout_delimited'; @import 'form_control_layout_icons'; @import 'form_control_layout_clear_button'; @import 'form_control_layout_custom_icon'; diff --git a/packages/eui/src/themes/amsterdam/overrides/_form_control_layout_delimited.scss b/packages/eui/src/themes/amsterdam/overrides/_form_control_layout_delimited.scss deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/eui/src/themes/amsterdam/overrides/_index.scss b/packages/eui/src/themes/amsterdam/overrides/_index.scss index 517e6936bf2..7fc02729ee9 100644 --- a/packages/eui/src/themes/amsterdam/overrides/_index.scss +++ b/packages/eui/src/themes/amsterdam/overrides/_index.scss @@ -1,3 +1,2 @@ @import 'data_grid'; -@import 'form_control_layout_delimited'; @import 'form_controls'; From 8631903630054e36b84b4b67a28c87d899b65f52 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sat, 10 Aug 2024 20:52:11 -0700 Subject: [PATCH 10/21] [EuiDatePicker] Fix styles that were relying on direct usage of `.euiFormControlLayoutDelimited` className - move inline styles to a nested obj for greater clarity - keeping the nesting now for laziness / since we might be rewriting date picker - `background-color` has some order shenanigans :T hopefully it's commented enough --- .../__snapshots__/date_picker.test.tsx.snap | 8 +- .../date_picker/date_picker.spec.tsx | 1 - .../date_picker/date_picker.styles.ts | 80 ++++++++++++------- .../components/date_picker/date_picker.tsx | 26 +++--- 4 files changed, 71 insertions(+), 44 deletions(-) diff --git a/packages/eui/src/components/date_picker/__snapshots__/date_picker.test.tsx.snap b/packages/eui/src/components/date_picker/__snapshots__/date_picker.test.tsx.snap index a28abb8cc98..80b76dd6b1b 100644 --- a/packages/eui/src/components/date_picker/__snapshots__/date_picker.test.tsx.snap +++ b/packages/eui/src/components/date_picker/__snapshots__/date_picker.test.tsx.snap @@ -5,10 +5,10 @@ exports[`EuiDatePicker localization accepts the locale prop 1`] = ` class="euiDatePicker testClass1 testClass2 emotion-euiDatePicker-inline-shadow-euiTestCss" >
{ 'have.class', 'euiFormControlLayoutIcons--static' ); - cy.get('.euiFormControlLayoutDelimited--isInvalid').should('exist'); }); it('renders as disabled', () => { diff --git a/packages/eui/src/components/date_picker/date_picker.styles.ts b/packages/eui/src/components/date_picker/date_picker.styles.ts index 329cdb2fb0d..90401385347 100644 --- a/packages/eui/src/components/date_picker/date_picker.styles.ts +++ b/packages/eui/src/components/date_picker/date_picker.styles.ts @@ -11,6 +11,12 @@ import { css } from '@emotion/react'; import { UseEuiTheme } from '../../services'; import { logicalCSS } from '../../global_styling'; import { euiShadowMedium } from '../../themes/amsterdam/global_styling/mixins'; +import { + euiFormControlDisabledStyles, + euiFormControlReadOnlyStyles, + euiFormControlDefaultShadow, + euiFormControlInvalidStyles, +} from '../form/form.styles'; export const euiDatePickerStyles = (euiThemeContext: UseEuiTheme) => { const { euiTheme } = euiThemeContext; @@ -19,35 +25,55 @@ export const euiDatePickerStyles = (euiThemeContext: UseEuiTheme) => { euiDatePicker: css` display: block; `, - inline: css` - .euiFormControlLayout { - ${logicalCSS('height', 'auto')} - ${logicalCSS('width', 'fit-content')} - background-color: transparent; - box-shadow: none; - padding: 0; - } - /* TODO: Extra specificity required to override .euiFormControlLayoutDelimited styles */ - .euiFormControlLayoutDelimited .euiFormControlLayout__childrenWrapper { - background-color: transparent; - flex-direction: column; /* Render form control icons below date picker */ - } + inline: { + inline: css` + .euiFormControlLayout { + ${logicalCSS('height', 'auto')} + ${logicalCSS('width', 'fit-content')} + box-shadow: none; + padding: 0; + } - .euiFormControlLayoutIcons { - justify-content: center; - ${logicalCSS('padding-bottom', euiTheme.size.s)} - } - `, - shadow: css` - .euiFormControlLayout { - ${euiShadowMedium(euiThemeContext)} - } + .euiFormControlLayout__childrenWrapper { + flex-direction: column; /* Render form control icons below date picker */ + } - /* TODO: Extra specificity required to override .euiFormControlLayoutDelimited styles */ - .euiFormControlLayoutDelimited .euiFormControlLayout__childrenWrapper { - background-color: ${euiTheme.colors.emptyShade}; - } - `, + .euiFormControlLayoutIcons { + justify-content: center; + ${logicalCSS('padding-bottom', euiTheme.size.s)} + } + `, + // Skip css`` to avoid generating an Emotion className + noShadow: ` + .euiFormControlLayout { + background-color: transparent; + } + `, + shadow: css` + .euiFormControlLayout { + background-color: ${euiTheme.colors.emptyShade}; + ${euiShadowMedium(euiThemeContext)} + } + `, + // Needs to come before shadow CSS so that it doesn't override their background-colors + invalid: css` + .euiFormControlLayout { + ${euiFormControlDefaultShadow(euiThemeContext, { withBorder: false })} + ${euiFormControlInvalidStyles(euiThemeContext)} + } + `, + // Should come after shadow CSS to override their background-colors + disabled: css` + .euiFormControlLayout { + ${euiFormControlDisabledStyles(euiThemeContext)} + } + `, + readOnly: css` + .euiFormControlLayout { + ${euiFormControlReadOnlyStyles(euiThemeContext)} + } + `, + }, }; }; diff --git a/packages/eui/src/components/date_picker/date_picker.tsx b/packages/eui/src/components/date_picker/date_picker.tsx index ae99fffe5e1..3e86e0a37df 100644 --- a/packages/eui/src/components/date_picker/date_picker.tsx +++ b/packages/eui/src/components/date_picker/date_picker.tsx @@ -188,20 +188,27 @@ export const EuiDatePicker: FunctionComponent = ({ utcOffset, ...rest }) => { + // Check for whether the passed `selected` moment date is valid + const isInvalid = + _isInvalid || (selected?.isValid() === false ? true : undefined); + const styles = useEuiMemoizedStyles(euiDatePickerStyles); const cssStyles = [ styles.euiDatePicker, - inline && styles.inline, - inline && shadow && styles.shadow, + ...(inline + ? [ + styles.inline.inline, + isInvalid && !(disabled || readOnly) && styles.inline.invalid, + shadow ? styles.inline.shadow : styles.inline.noShadow, + disabled && styles.inline.disabled, + readOnly && styles.inline.readOnly, + ] + : []), ]; const calendarStyles = useEuiMemoizedStyles(euiReactDatePickerStyles); const classes = classNames('euiDatePicker', className); - // Check for whether the passed `selected` moment date is valid - const isInvalid = - _isInvalid || (selected?.isValid() === false ? true : undefined); - // Passed to the default EuiFieldText input, not passed to custom inputs const defaultInputProps = !inline && !customInput ? { compressed, fullWidth } : undefined; @@ -297,12 +304,7 @@ export const EuiDatePicker: FunctionComponent = ({ isInvalid={isInvalid} isDisabled={disabled} readOnly={readOnly} - className={classNames({ - // Take advantage of `euiFormControlLayoutDelimited`'s replacement input styling - euiFormControlLayoutDelimited: inline, - 'euiFormControlLayoutDelimited--isInvalid': - inline && isInvalid && !disabled && !readOnly, - })} + isDelimited={inline} // Styling shortcut for inline calendars iconsPosition={inline ? 'static' : undefined} > {control} From 7ae705aaff0f7e0466fef5d15198b034b503e3f3 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sat, 10 Aug 2024 21:27:39 -0700 Subject: [PATCH 11/21] [EuiDatePickerRange] Fix regressed disabled background styles + remove unnecessary group/delimiter styles --- .../date_picker_range.test.tsx.snap | 86 +++++++++---------- .../date_picker/date_picker_range.styles.ts | 24 +++--- .../date_picker/date_picker_range.tsx | 7 ++ 3 files changed, 61 insertions(+), 56 deletions(-) diff --git a/packages/eui/src/components/date_picker/__snapshots__/date_picker_range.test.tsx.snap b/packages/eui/src/components/date_picker/__snapshots__/date_picker_range.test.tsx.snap index 333715894c9..d216171f869 100644 --- a/packages/eui/src/components/date_picker/__snapshots__/date_picker_range.test.tsx.snap +++ b/packages/eui/src/components/date_picker/__snapshots__/date_picker_range.test.tsx.snap @@ -7,10 +7,10 @@ exports[`EuiDatePickerRange is rendered 1`] = ` data-test-subj="test subject string" >
@@ -72,10 +72,10 @@ exports[`EuiDatePickerRange props compressed 1`] = ` class="euiDatePickerRange emotion-euiDatePickerRange" >
@@ -137,10 +137,10 @@ exports[`EuiDatePickerRange props disabled 1`] = ` class="euiDatePickerRange emotion-euiDatePickerRange" >
@@ -269,10 +269,10 @@ exports[`EuiDatePickerRange props inline renders 1`] = ` class="euiDatePickerRange emotion-euiDatePickerRangeInline-responsive-shadow" >
@@ -1402,10 +1402,10 @@ exports[`EuiDatePickerRange props isLoading 1`] = ` class="euiDatePickerRange emotion-euiDatePickerRange" >
@@ -1476,10 +1476,10 @@ exports[`EuiDatePickerRange props readOnly 1`] = ` class="euiDatePickerRange emotion-euiDatePickerRange" >
diff --git a/packages/eui/src/components/date_picker/date_picker_range.styles.ts b/packages/eui/src/components/date_picker/date_picker_range.styles.ts index c160967b251..e6cb89f7cbc 100644 --- a/packages/eui/src/components/date_picker/date_picker_range.styles.ts +++ b/packages/eui/src/components/date_picker/date_picker_range.styles.ts @@ -58,7 +58,6 @@ export const euiDatePickerRangeInlineStyles = ( ${logicalCSS('height', 'auto')} ${logicalCSS('width', 'fit-content')} ${logicalCSS('max-width', '100%')} - background-color: transparent; box-shadow: none; padding: 0; @@ -70,14 +69,6 @@ export const euiDatePickerRangeInlineStyles = ( background-color: transparent; } - /* Fix --group height when append/prepend are present */ - &.euiFormControlLayout--group { - & > *, - .euiFormControlLayoutDelimited__delimiter { - ${logicalCSS('height', 'auto')} - } - } - /* Display form control icons below both date pickers */ .euiFormControlLayoutIcons { justify-content: center; @@ -101,11 +92,18 @@ export const euiDatePickerRangeInlineStyles = ( shadow: css` .euiFormControlLayoutDelimited { ${euiShadowMedium(euiThemeContext)} - - .euiFormControlLayout__childrenWrapper { - background-color: ${euiTheme.colors.emptyShade}; - } } `, + + // Applied directly to EuiFormControlLayout so we can check if `disabled` + // and allow the disabled background-color to take precedence + formLayout: { + noShadow: css` + background-color: transparent; + `, + shadow: css` + background-color: ${euiTheme.colors.emptyShade}; + `, + }, }; }; diff --git a/packages/eui/src/components/date_picker/date_picker_range.tsx b/packages/eui/src/components/date_picker/date_picker_range.tsx index c51804c7b89..8e64e6ae760 100644 --- a/packages/eui/src/components/date_picker/date_picker_range.tsx +++ b/packages/eui/src/components/date_picker/date_picker_range.tsx @@ -216,6 +216,13 @@ export const EuiDatePickerRange: FunctionComponent = ({ isLoading={isLoading} append={inline ? undefined : append} prepend={inline ? undefined : prepend} + css={ + inline && + !disabled && + (shadow + ? inlineStyles.formLayout.shadow + : inlineStyles.formLayout.noShadow) + } /> ); From 92ff1efb7965c7c1f464da2b5475a63a838a703c Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sat, 10 Aug 2024 21:29:50 -0700 Subject: [PATCH 12/21] [EuiSuperDatePicker] Fix quick select only styling + remove now-unnecessary specificity - !important and other extra specificity comments can be removed - border radius is now completely handled by form control layouts and is no longer needed --- .../super_date_picker.test.tsx.snap | 10 +++++----- .../super_date_picker.styles.ts | 17 +++++++---------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/eui/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap b/packages/eui/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap index 293aae6dc8a..24d15886692 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap +++ b/packages/eui/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap @@ -769,7 +769,7 @@ exports[`EuiSuperDatePicker renders an EuiDatePickerRange 1`] = ` class="euiDatePickerRange emotion-euiDatePickerRange-euiSuperDatePicker__range-euiSuperDatePicker__formControlLayout-default" >