diff --git a/packages/eui/changelogs/upcoming/7987.md b/packages/eui/changelogs/upcoming/7987.md new file mode 100644 index 00000000000..557415e3b8a --- /dev/null +++ b/packages/eui/changelogs/upcoming/7987.md @@ -0,0 +1,5 @@ +- Updated `EuiDatePicker` to support `append` and `prepend` nodes in its form control layout + +**Bug fixes** + +- Fixed border rendering bug with inline `EuiDatePicker`s with `shadow={false}` diff --git a/packages/eui/src-docs/src/views/date_picker/states.js b/packages/eui/src-docs/src/views/date_picker/states.js index 8d4276764d7..670229ec138 100644 --- a/packages/eui/src-docs/src/views/date_picker/states.js +++ b/packages/eui/src-docs/src/views/date_picker/states.js @@ -21,8 +21,8 @@ export default () => { return ( /* DisplayToggles wrapper for Docs only */ -
- + <> + { placeholder="Example of an error" /> -
+ ); }; diff --git a/packages/eui/src/components/date_picker/date_picker.stories.tsx b/packages/eui/src/components/date_picker/date_picker.stories.tsx index cda75b4263f..4f1d681f66f 100644 --- a/packages/eui/src/components/date_picker/date_picker.stories.tsx +++ b/packages/eui/src/components/date_picker/date_picker.stories.tsx @@ -100,6 +100,8 @@ const meta: Meta = { isInvalid: false, isLoading: false, placeholder: '', + append: '', + prepend: '', // manually adding non-resolved prop types (extended from react-date-picker) calendarClassName: '', customInput: undefined, 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 90401385347..598a01615b5 100644 --- a/packages/eui/src/components/date_picker/date_picker.styles.ts +++ b/packages/eui/src/components/date_picker/date_picker.styles.ts @@ -31,7 +31,7 @@ export const euiDatePickerStyles = (euiThemeContext: UseEuiTheme) => { .euiFormControlLayout { ${logicalCSS('height', 'auto')} ${logicalCSS('width', 'fit-content')} - box-shadow: none; + border: none; padding: 0; } @@ -75,5 +75,14 @@ export const euiDatePickerStyles = (euiThemeContext: UseEuiTheme) => { } `, }, + + inGroup: css` + .euiFormControlLayout__childrenWrapper { + .euiPopover, + .react-datepicker__input-container { + ${logicalCSS('height', '100%')} + } + } + `, }; }; diff --git a/packages/eui/src/components/date_picker/date_picker.test.tsx b/packages/eui/src/components/date_picker/date_picker.test.tsx index c8a969a8edc..4897860527e 100644 --- a/packages/eui/src/components/date_picker/date_picker.test.tsx +++ b/packages/eui/src/components/date_picker/date_picker.test.tsx @@ -53,6 +53,29 @@ describe('EuiDatePicker', () => { expect(container.innerHTML).toContain('-compressed'); }); + test('append/prepend', () => { + const { container, rerender } = render( + + ); + const getAppend = () => + container.querySelector('.euiFormControlLayout__append'); + const getPrepend = () => + container.querySelector('.euiFormControlLayout__prepend'); + + expect(getAppend()).toHaveTextContent('hello'); + expect(getPrepend()).toHaveTextContent('world'); + + // Does not render if controlOnly + rerender(); + expect(getAppend()).not.toBeInTheDocument(); + expect(getPrepend()).not.toBeInTheDocument(); + + // Does not render if inline + rerender(); + expect(getAppend()).not.toBeInTheDocument(); + expect(getPrepend()).not.toBeInTheDocument(); + }); + // TODO: These tests/snapshots don't really do anything in Jest without // the corresponding popover opening. Should be switched to an E2E test instead describe.skip('popoverPlacement', () => { diff --git a/packages/eui/src/components/date_picker/date_picker.tsx b/packages/eui/src/components/date_picker/date_picker.tsx index 3e86e0a37df..a88ea36a0f8 100644 --- a/packages/eui/src/components/date_picker/date_picker.tsx +++ b/packages/eui/src/components/date_picker/date_picker.tsx @@ -22,7 +22,11 @@ import { useCombinedRefs, useEuiMemoizedStyles } from '../../services'; import { EuiI18nConsumer } from '../context'; import { CommonProps } from '../common'; import { PopoverAnchorPosition } from '../popover'; -import { EuiFormControlLayout, useEuiValidatableControl } from '../form'; +import { + EuiFormControlLayout, + EuiFormControlLayoutProps, + useEuiValidatableControl, +} from '../form'; import { EuiFormControlLayoutIconsProps } from '../form/form_control_layout/form_control_layout_icons'; import { ReactDatePicker, ReactDatePickerProps } from './react-datepicker'; @@ -138,9 +142,26 @@ interface EuiExtendedDatePickerProps */ popoverPlacement?: PopoverAnchorPosition; + /** + * Creates an input group with element(s) coming before the input. + * `string` | `ReactElement` or an array of these + * + * Ignored if `inline` or `controlOnly` are true. + */ + append?: EuiFormControlLayoutProps['append']; + /** + * Creates an input group with element(s) coming before the input. + * `string` | `ReactElement` or an array of these + * + * Ignored if `inline` or `controlOnly` are true. + */ + prepend?: EuiFormControlLayoutProps['prepend']; + /** * Completely removes form control layout wrapper and ignores - * iconType. Best used inside EuiFormControlLayoutDelimited. + * `iconType`, `prepend`, and `append`. + * + * Best used inside EuiFormControlLayoutDelimited. */ controlOnly?: boolean; } @@ -149,6 +170,7 @@ export type EuiDatePickerProps = CommonProps & EuiExtendedDatePickerProps; export const EuiDatePicker: FunctionComponent = ({ adjustDateOnChange = true, + append, calendarClassName, className, compressed, @@ -177,6 +199,7 @@ export const EuiDatePicker: FunctionComponent = ({ placeholder, popperClassName, popoverPlacement = 'downLeft', + prepend, readOnly, selected, shadow = true, @@ -297,15 +320,23 @@ export const EuiDatePicker: FunctionComponent = ({ {control} 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 e6cb89f7cbc..b2a63310649 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,7 @@ export const euiDatePickerRangeInlineStyles = ( ${logicalCSS('height', 'auto')} ${logicalCSS('width', 'fit-content')} ${logicalCSS('max-width', '100%')} - box-shadow: none; + border: none; padding: 0; .euiFormControlLayout__childrenWrapper {