use-focus-on-setting.tsx 1.6 KB

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