about summary refs log tree commit diff
path: root/src/components
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2025-02-03 12:27:58 -0800
committerGitHub <noreply@github.com>2025-02-03 20:27:58 +0000
commit23e62b18de9537b50c8b1df2b4744adc030501d0 (patch)
tree557037a964f2a8f7a3583ae84fc3b67b498c1ed2 /src/components
parent25991af7224cd76a8722f0579c00b73a211a84cc (diff)
downloadvoidsky-23e62b18de9537b50c8b1df2b4744adc030501d0.tar.zst
Date input improvements (#7639)
* add max date, use modern field for birthday input

* rm legacy date input

* handle simplifying to simpleDateString internally

* update jsdoc
Diffstat (limited to 'src/components')
-rw-r--r--src/components/dialogs/BirthDateSettings.tsx16
-rw-r--r--src/components/forms/DateField/index.android.tsx4
-rw-r--r--src/components/forms/DateField/index.shared.tsx2
-rw-r--r--src/components/forms/DateField/index.tsx24
-rw-r--r--src/components/forms/DateField/index.web.tsx7
-rw-r--r--src/components/forms/DateField/types.ts3
6 files changed, 35 insertions, 21 deletions
diff --git a/src/components/dialogs/BirthDateSettings.tsx b/src/components/dialogs/BirthDateSettings.tsx
index 8f47d05b0..9fbf378ac 100644
--- a/src/components/dialogs/BirthDateSettings.tsx
+++ b/src/components/dialogs/BirthDateSettings.tsx
@@ -12,12 +12,12 @@ import {
   usePreferencesSetBirthDateMutation,
 } from '#/state/queries/preferences'
 import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
-import {DateInput} from '#/view/com/util/forms/DateInput'
 import {atoms as a, useTheme} from '#/alf'
 import * as Dialog from '#/components/Dialog'
+import {DateField} from '#/components/forms/DateField'
 import {Loader} from '#/components/Loader'
+import {Text} from '#/components/Typography'
 import {Button, ButtonIcon, ButtonText} from '../Button'
-import {Text} from '../Typography'
 
 export function BirthDateSettingsDialog({
   control,
@@ -95,17 +95,13 @@ function BirthdayInner({
   return (
     <View style={a.gap_lg} testID="birthDateSettingsDialog">
       <View style={isIOS && [a.w_full, a.align_center]}>
-        <DateInput
-          handleAsUTC
+        <DateField
           testID="birthdayInput"
           value={date}
-          onChange={setDate}
-          buttonType="default-light"
-          buttonStyle={[a.rounded_sm]}
-          buttonLabelType="lg"
-          accessibilityLabel={_(msg`Birthday`)}
+          onChangeDate={newDate => setDate(new Date(newDate))}
+          label={_(msg`Birthday`)}
           accessibilityHint={_(msg`Enter your birth date`)}
-          accessibilityLabelledBy="birthDate"
+          maximumDate={new Date()}
         />
       </View>
 
diff --git a/src/components/forms/DateField/index.android.tsx b/src/components/forms/DateField/index.android.tsx
index 58f4d4f89..a6b6993dc 100644
--- a/src/components/forms/DateField/index.android.tsx
+++ b/src/components/forms/DateField/index.android.tsx
@@ -17,6 +17,7 @@ export function DateField({
   isInvalid,
   testID,
   accessibilityHint,
+  maximumDate,
 }: DateFieldProps) {
   const t = useTheme()
   const [open, setOpen] = React.useState(false)
@@ -67,6 +68,9 @@ export function DateField({
           aria-label={label}
           accessibilityLabel={label}
           accessibilityHint={accessibilityHint}
+          maximumDate={
+            maximumDate ? new Date(toSimpleDateString(maximumDate)) : undefined
+          }
         />
       )}
     </>
diff --git a/src/components/forms/DateField/index.shared.tsx b/src/components/forms/DateField/index.shared.tsx
index 7438f5622..7b03ba901 100644
--- a/src/components/forms/DateField/index.shared.tsx
+++ b/src/components/forms/DateField/index.shared.tsx
@@ -19,7 +19,7 @@ export function DateFieldButton({
   accessibilityHint,
 }: {
   label: string
-  value: string
+  value: string | Date
   onPress: () => void
   isInvalid?: boolean
   accessibilityHint?: string
diff --git a/src/components/forms/DateField/index.tsx b/src/components/forms/DateField/index.tsx
index 1c78d2abb..eca4d5cbd 100644
--- a/src/components/forms/DateField/index.tsx
+++ b/src/components/forms/DateField/index.tsx
@@ -16,10 +16,11 @@ export * as utils from '#/components/forms/DateField/utils'
 export const LabelText = TextField.LabelText
 
 /**
- * Date-only input. Accepts a date in the format YYYY-MM-DD, and reports date
- * changes in the same format.
+ * Date-only input. Accepts a string in the format YYYY-MM-DD, or a Date object.
+ * Date objects are converted to strings in the format YYYY-MM-DD.
+ * Returns a string in the format YYYY-MM-DD.
  *
- * For dates of unknown format, convert with the
+ * To generate a string in the format YYYY-MM-DD from a Date object, use the
  * `utils.toSimpleDateString(Date)` export of this file.
  */
 export function DateField({
@@ -29,6 +30,7 @@ export function DateField({
   label,
   isInvalid,
   accessibilityHint,
+  maximumDate,
 }: DateFieldProps) {
   const {_} = useLingui()
   const t = useTheme()
@@ -56,21 +58,29 @@ export function DateField({
         isInvalid={isInvalid}
         accessibilityHint={accessibilityHint}
       />
-      <Dialog.Outer control={control} testID={testID}>
+      <Dialog.Outer
+        control={control}
+        testID={testID}
+        nativeOptions={{preventExpansion: true}}>
         <Dialog.Handle />
-        <Dialog.Inner label={label}>
+        <Dialog.ScrollableInner label={label}>
           <View style={a.gap_lg}>
             <View style={[a.relative, a.w_full, a.align_center]}>
               <DatePicker
                 timeZoneOffsetInMinutes={0}
                 theme={t.name === 'light' ? 'light' : 'dark'}
-                date={new Date(value)}
+                date={new Date(toSimpleDateString(value))}
                 onDateChange={onChangeInternal}
                 mode="date"
                 testID={`${testID}-datepicker`}
                 aria-label={label}
                 accessibilityLabel={label}
                 accessibilityHint={accessibilityHint}
+                maximumDate={
+                  maximumDate
+                    ? new Date(toSimpleDateString(maximumDate))
+                    : undefined
+                }
               />
             </View>
             <Button
@@ -84,7 +94,7 @@ export function DateField({
               </ButtonText>
             </Button>
           </View>
-        </Dialog.Inner>
+        </Dialog.ScrollableInner>
       </Dialog.Outer>
     </>
   )
diff --git a/src/components/forms/DateField/index.web.tsx b/src/components/forms/DateField/index.web.tsx
index b764620e3..057ea1673 100644
--- a/src/components/forms/DateField/index.web.tsx
+++ b/src/components/forms/DateField/index.web.tsx
@@ -1,6 +1,6 @@
 import React from 'react'
 import {StyleSheet, TextInput, TextInputProps} from 'react-native'
-// @ts-ignore
+// @ts-expect-error untyped
 import {unstable_createElement} from 'react-native-web'
 
 import {DateFieldProps} from '#/components/forms/DateField/types'
@@ -39,6 +39,7 @@ export function DateField({
   isInvalid,
   testID,
   accessibilityHint,
+  maximumDate,
 }: DateFieldProps) {
   const handleOnChange = React.useCallback(
     (e: any) => {
@@ -56,12 +57,14 @@ export function DateField({
     <TextField.Root isInvalid={isInvalid}>
       <TextField.Icon icon={CalendarDays} />
       <Input
-        value={value}
+        value={toSimpleDateString(value)}
         label={label}
         onChange={handleOnChange}
         onChangeText={() => {}}
         testID={testID}
         accessibilityHint={accessibilityHint}
+        // @ts-expect-error not typed as <input type="date"> even though it is one
+        max={maximumDate ? toSimpleDateString(maximumDate) : undefined}
       />
     </TextField.Root>
   )
diff --git a/src/components/forms/DateField/types.ts b/src/components/forms/DateField/types.ts
index 5400cf903..1784b884f 100644
--- a/src/components/forms/DateField/types.ts
+++ b/src/components/forms/DateField/types.ts
@@ -1,8 +1,9 @@
 export type DateFieldProps = {
-  value: string
+  value: string | Date
   onChangeDate: (date: string) => void
   label: string
   isInvalid?: boolean
   testID?: string
   accessibilityHint?: string
+  maximumDate?: string | Date
 }