From 45ecb8b145b3734afa626bdc1cbb41065fb7226f Mon Sep 17 00:00:00 2001 From: Anna McPhee <30754158+annacmc@users.noreply.github.com> Date: Mon, 16 Sep 2024 20:26:36 -0600 Subject: [PATCH] Calypso UI Components: DateRange: Refactor "header" and "footer" areas of component (#94567) * simplify * move buttons to bottom * add new dateRangeFooter * refactor renderDateHelp into header * refactor header content out of index * styling header + footer * add description to readme * fix daterange styling regression * fix button import --- client/components/date-range/README.md | 1 + client/components/date-range/footer.tsx | 49 ++++++++++++++ client/components/date-range/header.tsx | 87 ++++++++++++++++--------- client/components/date-range/index.js | 60 ++++------------- client/components/date-range/style.scss | 8 ++- 5 files changed, 125 insertions(+), 80 deletions(-) create mode 100644 client/components/date-range/footer.tsx diff --git a/client/components/date-range/README.md b/client/components/date-range/README.md index bc3460cc2a3da..09a5153d17003 100644 --- a/client/components/date-range/README.md +++ b/client/components/date-range/README.md @@ -47,6 +47,7 @@ These props utilise the [Render Props](https://reactjs.org/docs/render-props.htm | ---------------------- | ---------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `renderTrigger(props)` | `Function` | undefined | render prop `Function` which will overide the default `DateRangeTrigger` component. Recieves same `props` object passed to `DateRangeTrigger` | | `renderHeader(props)` | `Function` | undefined | render prop `Function` which will overide the default `DateRangeHeader` component. Recieves same `props` object passed to `DateRangeHeader` | +| `renderFooter(props)` | `Function` | undefined | render prop `Function` which will overide the default `DateRangeFooter` component. Recieves same `props` object passed to `DateRangeFooter` | | `renderInputs(props)` | `Function` | undefined | render prop `Function` which will overide the default `DateRangeInputs` component. Recieves same `props` object passed to `DateRangeInputs` | ### General guidelines diff --git a/client/components/date-range/footer.tsx b/client/components/date-range/footer.tsx new file mode 100644 index 0000000000000..2101dbc364f0d --- /dev/null +++ b/client/components/date-range/footer.tsx @@ -0,0 +1,49 @@ +import { Button } from '@automattic/components'; +import { useTranslate } from 'i18n-calypso'; +import { FunctionComponent } from 'react'; + +// eslint-disable-next-line @typescript-eslint/no-empty-function +const noop = () => {}; + +interface Props { + onApplyClick: () => void; + onCancelClick: () => void; + applyButtonText: string | null | undefined; + cancelButtonText: string | null | undefined; +} + +const DateRangeFooter: FunctionComponent< Props > = ( { + onCancelClick = noop, + onApplyClick = noop, + cancelButtonText, + applyButtonText, +} ) => { + const translate = useTranslate(); + + const cancelText = cancelButtonText || translate( 'Cancel' ); + const applyText = applyButtonText || translate( 'Apply' ); + + return ( +
+ + +
+ ); +}; + +export default DateRangeFooter; diff --git a/client/components/date-range/header.tsx b/client/components/date-range/header.tsx index ae8f659c3a592..bb5e826954922 100644 --- a/client/components/date-range/header.tsx +++ b/client/components/date-range/header.tsx @@ -1,47 +1,72 @@ -import { Button } from '@automattic/components'; +import { Gridicon, Button } from '@automattic/components'; import { useTranslate } from 'i18n-calypso'; import { FunctionComponent } from 'react'; -// eslint-disable-next-line @typescript-eslint/no-empty-function -const noop = () => {}; - interface Props { - onApplyClick: () => void; - onCancelClick: () => void; - applyButtonText: string | null | undefined; - cancelButtonText: string | null | undefined; + customTitle?: string; + startDate: Date | null; + endDate: Date | null; + resetDates: () => void; } const DateRangeHeader: FunctionComponent< Props > = ( { - onCancelClick = noop, - onApplyClick = noop, - cancelButtonText, - applyButtonText, + customTitle, + startDate, + endDate, + resetDates, } ) => { const translate = useTranslate(); - const cancelText = cancelButtonText || translate( 'Cancel' ); - const applyText = applyButtonText || translate( 'Apply' ); + // Add this check at the beginning of the component + if ( startDate === undefined || endDate === undefined || resetDates === undefined ) { + return null; // or return a loading state + } + + const renderDateHelp = () => { + return ( +
+ { ! startDate && + ! endDate && + translate( '{{icon/}} Please select the {{em}}first{{/em}} day.', { + components: { + icon:
+ ); + }; return (
- - +
+ { customTitle ? ( +
{ customTitle }
+ ) : ( + renderDateHelp() + ) } +
); }; diff --git a/client/components/date-range/index.js b/client/components/date-range/index.js index fe62ce71f5ecc..5c22b5cd194e5 100644 --- a/client/components/date-range/index.js +++ b/client/components/date-range/index.js @@ -1,4 +1,4 @@ -import { Button, Popover, Gridicon } from '@automattic/components'; +import { Popover } from '@automattic/components'; import clsx from 'clsx'; import { localize } from 'i18n-calypso'; import moment from 'moment'; @@ -6,6 +6,7 @@ import PropTypes from 'prop-types'; import { createRef, Component } from 'react'; import { withLocalizedMoment } from 'calypso/components/localized-moment'; import DateRangePicker from './date-range-picker'; +import DateRangeFooter from './footer'; import DateRangeHeader from './header'; import DateRangeInputs from './inputs'; import Shortcuts from './shortcuts'; @@ -44,6 +45,7 @@ export class DateRange extends Component { showTriggerClear: PropTypes.bool, renderTrigger: PropTypes.func, renderHeader: PropTypes.func, + renderFooter: PropTypes.func, renderInputs: PropTypes.func, displayShortcuts: PropTypes.bool, rootClass: PropTypes.string, @@ -60,6 +62,7 @@ export class DateRange extends Component { showTriggerClear: true, renderTrigger: ( props ) => , renderHeader: ( props ) => , + renderFooter: ( props ) => , renderInputs: ( props ) => , displayShortcuts: false, rootClass: '', @@ -413,50 +416,19 @@ export class DateRange extends Component { this.handleDateRangeChange( startDate, endDate, 'custom_date_range' ); }; - renderDateHelp() { - const { startDate, endDate } = this.state; - - return ( -
- { ! startDate && - ! endDate && - this.props.translate( '{{icon/}} Please select the {{em}}first{{/em}} day.', { - components: { - icon:
- ); - } - /** * Renders the Popover component * @returns {import('react').Element} the Popover component */ renderPopover() { const headerProps = { + customTitle: this.props.customTitle, + startDate: this.state.startDate, + endDate: this.state.endDate, + resetDates: this.resetDates, + }; + + const footerProps = { onApplyClick: this.commitDates, onCancelClick: this.closePopoverAndRevert, }; @@ -486,16 +458,10 @@ export class DateRange extends Component { { this.props.overlay && (
{ this.props.overlay }
) } -
- { this.props.customTitle ? ( -
{ this.props.customTitle }
- ) : ( - this.renderDateHelp() - ) } -
+ { this.props.renderHeader( headerProps ) } { this.props.renderInputs( inputsProps ) } { this.renderDatePicker() } - { this.props.renderHeader( headerProps ) } + { this.props.renderFooter( footerProps ) } { /* Render shortcuts to the right of the calendar */ } { this.props.displayShortcuts && ( diff --git a/client/components/date-range/style.scss b/client/components/date-range/style.scss index 54ced1ff11277..59e041b4e0614 100644 --- a/client/components/date-range/style.scss +++ b/client/components/date-range/style.scss @@ -96,6 +96,12 @@ $date-range-mobile-layout-switch: $break-small; } .date-range__popover-header { + order: 1; + display: flex; + justify-content: left; +} + +.date-range__popover-footer { order: 4; display: flex; justify-content: flex-end; @@ -277,7 +283,6 @@ $date-range-mobile-layout-switch: $break-small; } } } - .DayPicker-Day--range:not(.DayPicker-Day--disabled):not(.DayPicker-Day--outside) { background-color: var(--date-range-picker-highlight-color); .date-picker__day { @@ -307,7 +312,6 @@ $date-range-mobile-layout-switch: $break-small; border-radius: 200px !important; } } - .date-range__popover-content { // Styling to fit optional shortcuts sidebar display: flex; align-items: stretch; // Ensure children stretch to full height