@@ -194,6 +194,31 @@ function formatOverrideTime(value: string) {
194194 return `${ day } ${ time } `
195195}
196196
197+ /*
198+ * Let a mobile bottom sheet paint before opening its keyboard. Focusing an
199+ * input during the same render as the sheet can leave the sheet behind the
200+ * keyboard in embedded Home Assistant views until the user types.
201+ */
202+ function useDelayedSheetInputFocus ( open : boolean ) {
203+ const inputRef = useRef < HTMLInputElement | null > ( null )
204+
205+ useEffect ( ( ) => {
206+ if ( ! open ) {
207+ return
208+ }
209+
210+ const timeout = window . setTimeout ( ( ) => {
211+ inputRef . current ?. focus ( )
212+ } , 120 )
213+
214+ return ( ) => {
215+ window . clearTimeout ( timeout )
216+ }
217+ } , [ open ] )
218+
219+ return inputRef
220+ }
221+
197222type RateType = 'import' | 'export'
198223
199224function getManualRateOverride ( slotMinute : number , type : RateType , overrides : PlanOverrides ) {
@@ -242,6 +267,7 @@ function RateCell({
242267 const [ error , setError ] = useState < string | null > ( null )
243268
244269 const controlRef = useRef < HTMLDivElement | null > ( null )
270+ const inputRef = useDelayedSheetInputFocus ( open )
245271
246272 useEffect ( ( ) => {
247273 if ( ! open ) {
@@ -443,7 +469,7 @@ function RateCell({
443469 inputMode = "decimal"
444470 value = { value }
445471 onChange = { ( event ) => setValue ( event . target . value ) }
446- autoFocus
472+ ref = { inputRef }
447473 disabled = { saving }
448474 />
449475
@@ -506,6 +532,7 @@ function LoadCell({
506532 const [ saving , setSaving ] = useState ( false )
507533 const [ error , setError ] = useState < string | null > ( null )
508534 const controlRef = useRef < HTMLDivElement | null > ( null )
535+ const inputRef = useDelayedSheetInputFocus ( open )
509536
510537 useEffect ( ( ) => {
511538 if ( ! open ) {
@@ -629,7 +656,7 @@ function LoadCell({
629656 inputMode = "decimal"
630657 value = { value }
631658 onChange = { ( event ) => setValue ( event . target . value ) }
632- autoFocus
659+ ref = { inputRef }
633660 disabled = { saving }
634661 />
635662
@@ -675,6 +702,7 @@ function TargetCell({
675702 onOverrideSubmitted
676703} : TargetCellProps ) {
677704 const controlRef = useRef < HTMLDivElement | null > ( null )
705+ const inputRef = useDelayedSheetInputFocus ( open )
678706
679707 const [ value , setValue ] = useState ( '' )
680708
@@ -862,7 +890,7 @@ function TargetCell({
862890 inputMode = "numeric"
863891 value = { value }
864892 onChange = { ( event ) => setValue ( event . target . value ) }
865- autoFocus
893+ ref = { inputRef }
866894 disabled = { saving }
867895 />
868896
@@ -1332,13 +1360,22 @@ export default function PlanTable({
13321360 document . documentElement . style . setProperty ( '--plan-mobile-keyboard-offset' , `${ offset } px` )
13331361 }
13341362
1363+ function updateAfterKeyboardAnimation ( ) {
1364+ updateKeyboardOffset ( )
1365+ requestAnimationFrame ( updateKeyboardOffset )
1366+ window . setTimeout ( updateKeyboardOffset , 150 )
1367+ window . setTimeout ( updateKeyboardOffset , 350 )
1368+ }
1369+
13351370 updateKeyboardOffset ( )
13361371 viewport . addEventListener ( 'resize' , updateKeyboardOffset )
13371372 viewport . addEventListener ( 'scroll' , updateKeyboardOffset )
1373+ document . addEventListener ( 'focusin' , updateAfterKeyboardAnimation )
13381374
13391375 return ( ) => {
13401376 viewport . removeEventListener ( 'resize' , updateKeyboardOffset )
13411377 viewport . removeEventListener ( 'scroll' , updateKeyboardOffset )
1378+ document . removeEventListener ( 'focusin' , updateAfterKeyboardAnimation )
13421379 document . documentElement . style . removeProperty ( '--plan-mobile-keyboard-offset' )
13431380 }
13441381 } , [ ] )
0 commit comments