From 677afe859b435110c4e29f81eccc3f26d367be62 Mon Sep 17 00:00:00 2001 From: Mattias Andersson Date: Mon, 2 Sep 2024 10:52:29 +0200 Subject: [PATCH] - In travel calendar, add support for custom placeholder when text input is not in focus. --- .../TravelDateCalendar.stories.tsx | 15 +++++++++ .../TravelDateCalendar.tsx | 3 ++ .../TravelDateRangeCalendar.stories.tsx | 18 +++++++++++ .../TravelDateRangeCalendar.tsx | 6 ++++ .../TravelDateInput.stories.tsx | 15 +++++++++ .../travel-date-input/TravelDateInput.tsx | 3 ++ .../TravelDateRangeInput.stories.tsx | 18 +++++++++++ .../TravelDateRangeInput.tsx | 6 ++++ .../TravelDateSingleTextInputField.tsx | 3 ++ .../components/TravelDateTextInput.tsx | 32 ++++++++++++++++++- .../components/TravelDateTextInputFields.tsx | 6 ++++ 11 files changed, 124 insertions(+), 1 deletion(-) diff --git a/packages/calendar/src/components/calendar-types/travel-date-calendar/TravelDateCalendar.stories.tsx b/packages/calendar/src/components/calendar-types/travel-date-calendar/TravelDateCalendar.stories.tsx index 616272738..d7e3bc50c 100644 --- a/packages/calendar/src/components/calendar-types/travel-date-calendar/TravelDateCalendar.stories.tsx +++ b/packages/calendar/src/components/calendar-types/travel-date-calendar/TravelDateCalendar.stories.tsx @@ -168,3 +168,18 @@ export const ParseDate = () => { ); }; + +export const WithBlurPlaceholders = () => { + const [value, setValue] = useState(""); + + return ( +
+ +
+ ); +}; diff --git a/packages/calendar/src/components/calendar-types/travel-date-calendar/TravelDateCalendar.tsx b/packages/calendar/src/components/calendar-types/travel-date-calendar/TravelDateCalendar.tsx index 8028f5975..127f4db27 100644 --- a/packages/calendar/src/components/calendar-types/travel-date-calendar/TravelDateCalendar.tsx +++ b/packages/calendar/src/components/calendar-types/travel-date-calendar/TravelDateCalendar.tsx @@ -25,6 +25,7 @@ export interface TravelDateCalendarProps dateTestId?: (date: Date) => string | undefined; previousMonthButtonTestId?: string; nextMonthButtonTestId?: string; + placeholderWhenBlurred?: string; } export const TravelDateCalendar: React.FC = ({ @@ -35,6 +36,7 @@ export const TravelDateCalendar: React.FC = ({ initialMonthInFocus, previousMonthButtonAriaLabel = "Previous month", nextMonthButtonAriaLabel = "Next month", + placeholderWhenBlurred, heading, headingLevel, numMonthsInMonthPicker = 12, @@ -74,6 +76,7 @@ export const TravelDateCalendar: React.FC = ({ localeCode={localeCode} label={label} calendarSize={size} + placeholderWhenBlurred={placeholderWhenBlurred} /> { ); }; + +export const WithBlurPlaceholders = () => { + const [value, setValue] = useState( + undefined + ); + + return ( +
+ +
+ ); +}; diff --git a/packages/calendar/src/components/calendar-types/travel-date-range-calendar/TravelDateRangeCalendar.tsx b/packages/calendar/src/components/calendar-types/travel-date-range-calendar/TravelDateRangeCalendar.tsx index eefe93a48..9e8a5c87a 100644 --- a/packages/calendar/src/components/calendar-types/travel-date-range-calendar/TravelDateRangeCalendar.tsx +++ b/packages/calendar/src/components/calendar-types/travel-date-range-calendar/TravelDateRangeCalendar.tsx @@ -27,6 +27,8 @@ export interface TravelDateRangeCalendarProps dateTestId?: (date: Date) => string | undefined; previousMonthButtonTestId?: string; nextMonthButtonTestId?: string; + placeholderWhenBlurredStartDate?: string; + placeholderWhenBlurredEndDate?: string; } export const TravelDateRangeCalendar: React.FC< @@ -48,6 +50,8 @@ export const TravelDateRangeCalendar: React.FC< dateTestId, previousMonthButtonTestId, nextMonthButtonTestId, + placeholderWhenBlurredStartDate, + placeholderWhenBlurredEndDate, }) => { const inputProps = useTravelDateRangeInput( value, @@ -79,6 +83,8 @@ export const TravelDateRangeCalendar: React.FC< startDateLabel={startDateLabel} endDateLabel={endDateLabel} calendarSize={size} + placeholderWhenBlurredStartDate={placeholderWhenBlurredStartDate} + placeholderWhenBlurredEndDate={placeholderWhenBlurredEndDate} /> { ); }; + +export const WithBlurPlaceholders = () => { + const [value, setValue] = useState(""); + + return ( +
+ +
+ ); +}; diff --git a/packages/calendar/src/components/input-types/travel-date-input/TravelDateInput.tsx b/packages/calendar/src/components/input-types/travel-date-input/TravelDateInput.tsx index d7d69eb58..c0e49578b 100644 --- a/packages/calendar/src/components/input-types/travel-date-input/TravelDateInput.tsx +++ b/packages/calendar/src/components/input-types/travel-date-input/TravelDateInput.tsx @@ -49,6 +49,7 @@ export interface TravelDateInputProps dateTestId?: (date: Date) => string | undefined; previousMonthButtonTestId?: string; nextMonthButtonTestId?: string; + placeholderWhenBlurred?: string; } export const TravelDateInput: React.FC = ({ @@ -59,6 +60,7 @@ export const TravelDateInput: React.FC = ({ initialMonthInFocus, previousMonthButtonAriaLabel = "Previous month", nextMonthButtonAriaLabel = "Next month", + placeholderWhenBlurred, heading, headingLevel, numMonthsInMonthPicker = 12, @@ -170,6 +172,7 @@ export const TravelDateInput: React.FC = ({ label={label} onFocus={showCalendar} calendarSize={size} + placeholderWhenBlurred={placeholderWhenBlurred} /> diff --git a/packages/calendar/src/components/input-types/travel-date-range-input/TravelDateRangeInput.stories.tsx b/packages/calendar/src/components/input-types/travel-date-range-input/TravelDateRangeInput.stories.tsx index 873aba8a3..dbe4811bb 100644 --- a/packages/calendar/src/components/input-types/travel-date-range-input/TravelDateRangeInput.stories.tsx +++ b/packages/calendar/src/components/input-types/travel-date-range-input/TravelDateRangeInput.stories.tsx @@ -260,3 +260,21 @@ export const WithPresets = () => { ); }; + +export const WithBlurPlaceholders = () => { + const [value, setValue] = useState( + undefined + ); + + return ( +
+ +
+ ); +}; diff --git a/packages/calendar/src/components/input-types/travel-date-range-input/TravelDateRangeInput.tsx b/packages/calendar/src/components/input-types/travel-date-range-input/TravelDateRangeInput.tsx index 6b94250f2..da29e1cb1 100644 --- a/packages/calendar/src/components/input-types/travel-date-range-input/TravelDateRangeInput.tsx +++ b/packages/calendar/src/components/input-types/travel-date-range-input/TravelDateRangeInput.tsx @@ -51,6 +51,8 @@ export interface TravelDateRangeInputProps dateTestId?: (date: Date) => string | undefined; previousMonthButtonTestId?: string; nextMonthButtonTestId?: string; + placeholderWhenBlurredStartDate?: string; + placeholderWhenBlurredEndDate?: string; } export const TravelDateRangeInput: React.FC = ({ @@ -62,6 +64,8 @@ export const TravelDateRangeInput: React.FC = ({ initialMonthInFocus, previousMonthButtonAriaLabel = "Previous month", nextMonthButtonAriaLabel = "Next month", + placeholderWhenBlurredStartDate, + placeholderWhenBlurredEndDate, heading, headingLevel, numMonthsInMonthPicker = 12, @@ -173,6 +177,8 @@ export const TravelDateRangeInput: React.FC = ({ endDateLabel={endDateLabel} onFocus={showCalendar} calendarSize={size} + placeholderWhenBlurredStartDate={placeholderWhenBlurredStartDate} + placeholderWhenBlurredEndDate={placeholderWhenBlurredEndDate} /> diff --git a/packages/calendar/src/features/travel-calendar/components/TravelDateSingleTextInputField.tsx b/packages/calendar/src/features/travel-calendar/components/TravelDateSingleTextInputField.tsx index b6661ab1e..914182729 100644 --- a/packages/calendar/src/features/travel-calendar/components/TravelDateSingleTextInputField.tsx +++ b/packages/calendar/src/features/travel-calendar/components/TravelDateSingleTextInputField.tsx @@ -14,6 +14,7 @@ export interface TravelDateSingleTextInputFieldProps { label?: string; onFocus?: () => void; calendarSize: TravelCalendarSizeVariant; + placeholderWhenBlurred: string | undefined; } export const TravelDateSingleTextInputField: React.FC< @@ -25,6 +26,7 @@ export const TravelDateSingleTextInputField: React.FC< localeCode, onFocus, calendarSize, + placeholderWhenBlurred, }) => { const { mask, placeholder } = useMemo(() => { const dateFormatForLocaleCode = getDateFormatForLocaleCode(localeCode); @@ -50,6 +52,7 @@ export const TravelDateSingleTextInputField: React.FC< label={label} placeholder={placeholder} calendarSize={calendarSize} + placeholderWhenBlurred={placeholderWhenBlurred} /> ); diff --git a/packages/calendar/src/features/travel-calendar/components/TravelDateTextInput.tsx b/packages/calendar/src/features/travel-calendar/components/TravelDateTextInput.tsx index 6f4685740..389c8bccb 100644 --- a/packages/calendar/src/features/travel-calendar/components/TravelDateTextInput.tsx +++ b/packages/calendar/src/features/travel-calendar/components/TravelDateTextInput.tsx @@ -3,7 +3,7 @@ import { LabelledTextInput, LabelledTextInputProps, } from "@stenajs-webui/forms"; -import { useRef } from "react"; +import { FocusEventHandler, useCallback, useRef, useState } from "react"; import { InputMask, InputMaskPipe, @@ -21,6 +21,7 @@ export interface TravelDateTextInputProps extends LabelledTextInputProps { placeholderChar?: string; showMask?: boolean; calendarSize: TravelCalendarSizeVariant; + placeholderWhenBlurred: string | undefined; } export const TravelDateTextInput: React.FC = ({ @@ -34,9 +35,15 @@ export const TravelDateTextInput: React.FC = ({ placeholderChar, showMask, calendarSize, + onFocus, + onBlur, + placeholderWhenBlurred, + placeholder, ...inputProps }) => { const inputRef = useRef(null); + const [isFocused, setIsFocused] = useState(false); + const { onChange: maskedOnChange } = useMaskedInput( inputRef, onChange, @@ -50,10 +57,33 @@ export const TravelDateTextInput: React.FC = ({ showMask ); + const onFocusHandler = useCallback>( + (ev) => { + onFocus?.(ev); + setIsFocused(true); + }, + [onFocus] + ); + + const onBlurHandler = useCallback>( + (ev) => { + onBlur?.(ev); + setIsFocused(false); + }, + [onBlur] + ); + + const activePlaceholder = isFocused + ? placeholder + : placeholderWhenBlurred ?? placeholder; + return ( void; calendarSize: TravelCalendarSizeVariant; + placeholderWhenBlurredStartDate: string | undefined; + placeholderWhenBlurredEndDate: string | undefined; } export const TravelDateTextInputFields: React.FC< @@ -30,6 +32,8 @@ export const TravelDateTextInputFields: React.FC< endDateLabel = "To", onFocus, calendarSize, + placeholderWhenBlurredStartDate, + placeholderWhenBlurredEndDate, }) => { const { mask, placeholder } = useMemo(() => { const dateFormatForLocaleCode = getDateFormatForLocaleCode(localeCode); @@ -60,6 +64,7 @@ export const TravelDateTextInputFields: React.FC< label={startDateLabel} borderRadiusVariant={"onlyLeft"} placeholder={placeholder} + placeholderWhenBlurred={placeholderWhenBlurredStartDate} calendarSize={calendarSize} />