@@ -24,7 +24,14 @@ import {
24
24
type InputHTMLAttributes ,
25
25
} from 'react' ;
26
26
import type { Temporal } from 'temporal-polyfill' ;
27
- import { flip , offset , shift , size , useFloating } from '@floating-ui/react-dom' ;
27
+ import {
28
+ flip ,
29
+ offset ,
30
+ shift ,
31
+ size ,
32
+ useFloating ,
33
+ type Placement ,
34
+ } from '@floating-ui/react-dom' ;
28
35
import { Calendar as CalendarIcon } from '@sumup-oss/icons' ;
29
36
30
37
import type { ClickEvent } from '../../types/events.js' ;
@@ -134,6 +141,10 @@ export interface DateInputProps
134
141
* A hint to the user agent specifying how to prefill the input.
135
142
*/
136
143
autoComplete ?: 'bday' ;
144
+ /**
145
+ * One of the accepted placement values. Defaults to `bottom-end`.
146
+ */
147
+ placement ?: Placement ;
137
148
}
138
149
139
150
/**
@@ -171,6 +182,7 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>(
171
182
monthInputLabel,
172
183
dayInputLabel,
173
184
autoComplete,
185
+ placement = 'bottom-end' ,
174
186
className,
175
187
style,
176
188
...props
@@ -180,7 +192,7 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>(
180
192
const isMobile = useMedia ( '(max-width: 479px)' ) ;
181
193
182
194
const inputRef = useRef < HTMLInputElement > ( null ) ;
183
- const fieldRef = useRef < HTMLDivElement > ( null ) ;
195
+ const calendarButtonRef = useRef < HTMLDivElement > ( null ) ;
184
196
const dialogRef = useRef < HTMLDialogElement > ( null ) ;
185
197
186
198
const dialogId = useId ( ) ;
@@ -208,21 +220,24 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>(
208
220
const [ open , setOpen ] = useState ( false ) ;
209
221
const [ selection , setSelection ] = useState < Temporal . PlainDate > ( ) ;
210
222
223
+ const padding = 16 ; // px
224
+
211
225
const { floatingStyles, update } = useFloating ( {
212
226
open,
213
- placement : 'bottom-start' ,
227
+ placement,
214
228
middleware : [
215
229
offset ( 4 ) ,
216
- flip ( { fallbackAxisSideDirection : 'end' , crossAxis : false } ) ,
217
- shift ( ) ,
230
+ flip ( { padding , fallbackAxisSideDirection : 'start' } ) ,
231
+ shift ( { padding } ) ,
218
232
size ( {
233
+ padding,
219
234
apply ( { availableHeight, elements } ) {
220
235
elements . floating . style . maxHeight = `${ availableHeight } px` ;
221
236
} ,
222
237
} ) ,
223
238
] ,
224
239
elements : {
225
- reference : fieldRef . current ,
240
+ reference : calendarButtonRef . current ,
226
241
floating : dialogRef . current ,
227
242
} ,
228
243
} ) ;
@@ -370,7 +385,7 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>(
370
385
optionalLabel = { optionalLabel }
371
386
/>
372
387
</ FieldLegend >
373
- < div ref = { fieldRef } className = { classes . wrapper } >
388
+ < div className = { classes . wrapper } >
374
389
< input
375
390
type = "date"
376
391
ref = { applyMultipleRefs ( ref , inputRef ) }
@@ -462,6 +477,7 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>(
462
477
} ) }
463
478
</ div >
464
479
< IconButton
480
+ ref = { calendarButtonRef }
465
481
type = "button"
466
482
icon = { CalendarIcon }
467
483
variant = "secondary"
0 commit comments