use-focus-on-setting.tsx 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import { useEffect, useState } from 'react'
  2. import { useSettingsModalContext } from '../context/settings-modal-context'
  3. /**
  4. * A hook to scroll to and focus on a specific setting in the settings modal
  5. */
  6. export default function useFocusOnSetting() {
  7. const { activeTab, setActiveTab, settingToTabMap, settingToFocus } =
  8. useSettingsModalContext()
  9. const [eltToScrollTo, setEltToScrollTo] = useState<{
  10. tab: string | undefined
  11. element: HTMLElement | null
  12. } | null>(null)
  13. useEffect(() => {
  14. if (settingToFocus) {
  15. const newActiveTab = settingToTabMap.get(settingToFocus)
  16. const settingElt: HTMLDivElement | null = document.querySelector(
  17. `#setting-${settingToFocus}`
  18. )
  19. const settingToFocusElt: HTMLElement | null =
  20. settingElt?.querySelector('input, select, button') ?? settingElt
  21. settingElt?.classList.add('ide-setting-highlighted')
  22. setTimeout(() => {
  23. settingElt?.classList.remove('ide-setting-highlighted')
  24. }, 2000)
  25. setActiveTab(newActiveTab)
  26. setEltToScrollTo({ tab: newActiveTab, element: settingToFocusElt })
  27. }
  28. // clear the focus setting
  29. window.dispatchEvent(
  30. new CustomEvent('ui.focus-setting', { detail: undefined })
  31. )
  32. }, [settingToFocus, activeTab, setActiveTab, settingToTabMap])
  33. // Scroll to the focused setting, once the correct tab is open
  34. useEffect(() => {
  35. if (!eltToScrollTo) {
  36. return
  37. }
  38. const { tab, element } = eltToScrollTo
  39. if (tab === activeTab) {
  40. element?.scrollIntoView({
  41. block: 'center',
  42. behavior: 'smooth',
  43. })
  44. element?.focus()
  45. setEltToScrollTo(null)
  46. }
  47. }, [eltToScrollTo, activeTab])
  48. }