Skip to content

Commit

Permalink
feat: add experimental prop to force number keyboard on ios
Browse files Browse the repository at this point in the history
  • Loading branch information
karrui committed Nov 9, 2023
1 parent 467e645 commit ba94a97
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 1 deletion.
9 changes: 9 additions & 0 deletions react/src/DatePicker/DatePickerContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ interface DatePickerContextReturn {
| 'showOutsideDays'
| 'showTodayButton'
>
inputPattern?: string
}

const DatePickerContext = createContext<DatePickerContextReturn | null>(null)
Expand Down Expand Up @@ -103,6 +104,7 @@ const useProvideDatePicker = ({
refocusOnClose = true,
ssr,
size,
experimental_forceIosNumberKeyboard,
...props
}: DatePickerProps): DatePickerContextReturn => {
const initialFocusRef = useRef<HTMLInputElement>(null)
Expand All @@ -112,6 +114,12 @@ const useProvideDatePicker = ({

const isMobile = useIsMobile({ ssr })

const inputPattern = useMemo(() => {
if (experimental_forceIosNumberKeyboard) {
return '[0-9]*'
}
}, [experimental_forceIosNumberKeyboard])

const disclosureProps = useDisclosure({
onClose: () => {
if (!refocusOnClose) return
Expand Down Expand Up @@ -257,5 +265,6 @@ const useProvideDatePicker = ({
size,
disclosureProps,
calendarProps,
inputPattern,
}
}
9 changes: 8 additions & 1 deletion react/src/DatePicker/components/DatePickerInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const DatePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
inputRef,
internalValue,
size,
inputPattern,
} = useDatePicker()

const mergedInputRef = useMergeRefs(inputRef, ref)
Expand Down Expand Up @@ -55,6 +56,7 @@ export const DatePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
{hasMounted ? (
<Input
size={size}
pattern={inputPattern}
inputMode="numeric" // Nudge Android mobile keyboard to be numeric.
as={ReactInputMask}
mask="99/99/9999"
Expand All @@ -69,7 +71,12 @@ export const DatePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
isReadOnly={fcProps.isReadOnly || !allowManualInput}
/>
) : (
<Input size={size} inputMode="numeric" placeholder={placeholder} />
<Input
size={size}
inputMode="numeric"
placeholder={placeholder}
pattern={inputPattern}
/>
)}
<InputRightAddon p={0} border="none">
<CalendarButton />
Expand Down
12 changes: 12 additions & 0 deletions react/src/DatePicker/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ export interface DatePickerBaseProps
* @defaultValue `true`
*/
closeCalendarOnChange?: boolean

/**
* Whether to force the number keyboard on iOS.
*
* This will set the inputmode to `numeric` and pattern to `[0-9]*` on the input, which
* will force the number keyboard to show on iOS for a better user experience.
*
* ⚠️ This will break native form input validation if set, since the value of the input
* will always be `"DD/MM/YYYY"`, which does not conform to the input.
* To prevent native form validation, set `noValidate` on the parent `form` component.
*/
experimental_forceIosNumberKeyboard?: boolean
/**
* Whether to refocus date picker when calendar is closed.
* @defaultValue `true`
Expand Down
9 changes: 9 additions & 0 deletions react/src/DateRangePicker/DateRangePickerContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ interface DateRangePickerContextReturn {
| 'defaultFocusedDate'
| 'showTodayButton'
>
inputPattern?: string
}

const DateRangePickerContext =
Expand Down Expand Up @@ -109,6 +110,7 @@ const useProvideDateRangePicker = ({
refocusOnClose = true,
size,
ssr,
experimental_forceIosNumberKeyboard,
...props
}: DateRangePickerProps): DateRangePickerContextReturn => {
const initialFocusRef = useRef<HTMLInputElement>(null)
Expand All @@ -119,6 +121,12 @@ const useProvideDateRangePicker = ({

const isMobile = useIsMobile({ ssr })

const inputPattern = useMemo(() => {
if (experimental_forceIosNumberKeyboard) {
return '[0-9]*'
}
}, [experimental_forceIosNumberKeyboard])

const disclosureProps = useDisclosure({
onClose: () => {
if (!refocusOnClose) return
Expand Down Expand Up @@ -343,5 +351,6 @@ const useProvideDateRangePicker = ({
disclosureProps,
labelSeparator,
calendarProps,
inputPattern,
}
}
5 changes: 5 additions & 0 deletions react/src/DateRangePicker/components/DateRangePickerInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const DateRangePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
handleEndDateChange,
internalValue: [startDate, endDate],
size,
inputPattern,
} = useDateRangePicker()

const mergedStartInputRef = useMergeRefs(startInputRef, ref)
Expand Down Expand Up @@ -75,6 +76,7 @@ export const DateRangePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
variant="unstyled"
aria-label="Start date of range"
inputMode="numeric" // Nudge Android mobile keyboard to be numeric
pattern={inputPattern}
sx={styles.field}
width="6rem"
as={ReactInputMask}
Expand All @@ -92,6 +94,7 @@ export const DateRangePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
) : (
<Input
size={size}
pattern={inputPattern}
variant="unstyled"
inputMode="numeric"
placeholder={placeholder}
Expand All @@ -104,6 +107,7 @@ export const DateRangePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
<Input
variant="unstyled"
size={size}
pattern={inputPattern}
aria-label="Start date of range"
inputMode="numeric" // Nudge Android mobile keyboard to be numeric
sx={styles.field}
Expand All @@ -123,6 +127,7 @@ export const DateRangePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
) : (
<Input
size={size}
pattern={inputPattern}
variant="unstyled"
inputMode="numeric"
placeholder={placeholder}
Expand Down

0 comments on commit ba94a97

Please sign in to comment.