Skip to main content
The ModalStore is a simple global state manager that tracks whether any modal is currently open in the application. This is useful for adjusting UI elements (like toast notifications or floating buttons) when modals are displayed.

Import

import { useModalStore } from "../stores/ModalStore"

Usage

const Login = () => {
  const setModalOpen = useModalStore(state => state.setModalOpen)
  const [isLoginModalOpen, setIsLoginModalOpen] = useState(false)

  const openModal = () => {
    setIsLoginModalOpen(true)
    setModalOpen(true) // Notify global state
  }

  const closeModal = () => {
    setIsLoginModalOpen(false)
    setModalOpen(false) // Notify global state
  }

  return (
    <>
      <button onClick={openModal}>Sign in</button>
      <Modal isOpen={isLoginModalOpen} closeModal={closeModal}>
        {/* Modal content */}
      </Modal>
    </>
  )
}
const AddBookmark = () => {
  const isAnyModalOpen = useModalStore(state => state.isAnyModalOpen)

  return (
    <div 
      className={`fixed transition-all ${
        isAnyModalOpen ? "-bottom-20" : "bottom-4"
      }`}
    >
      {/* Floating input that moves down when modal is open */}
    </div>
  )
}
const App = () => {
  const isAnyModalOpen = useModalStore(state => state.isAnyModalOpen)

  return (
    <main>
      <Toaster 
        position="bottom-center" 
        offset={{ 
          bottom: isAnyModalOpen ? "16px" : "102px" 
        }}
      />
    </main>
  )
}

State Properties

isAnyModalOpen
boolean
default:"false"
Indicates whether any modal is currently open in the application. Use this to adjust positioning of floating elements, toast notifications, or other UI components that should respond to modal state.

Methods

setModalOpen

Sets the global modal state.
isOpen
boolean
required
Set to true when opening a modal, false when closing it.
const setModalOpen = useModalStore(state => state.setModalOpen)

// When opening a modal
setModalOpen(true)

// When closing a modal
setModalOpen(false)

Type Definitions

type ModalState = {
  isAnyModalOpen: boolean
  setModalOpen: (isOpen: boolean) => void
}

Implementation Details

  • State Management: Uses Zustand for lightweight global state
  • Single Source of Truth: Tracks whether ANY modal is open, not specific modals
  • No Modal Logic: This store only tracks state; actual modal rendering and logic should be handled by individual components
  • UI Coordination: Primarily used to coordinate UI elements that need to adjust when modals are present

Common Patterns

const CustomModal = ({ isOpen, onClose, children }) => {
  const setModalOpen = useModalStore(state => state.setModalOpen)

  useEffect(() => {
    setModalOpen(isOpen)
  }, [isOpen, setModalOpen])

  const handleClose = () => {
    setModalOpen(false)
    onClose()
  }

  return (
    <Dialog open={isOpen} onClose={handleClose}>
      {children}
    </Dialog>
  )
}

Responsive UI Elements

const FloatingButton = () => {
  const isAnyModalOpen = useModalStore(state => state.isAnyModalOpen)

  return (
    <button
      className={`fixed bottom-4 right-4 transition-transform ${
        isAnyModalOpen ? 'translate-y-20' : 'translate-y-0'
      }`}
    >
      Add
    </button>
  )
}

Toast Offset Adjustment

// Adjust toast position based on whether modals are open
const isAnyModalOpen = useModalStore(state => state.isAnyModalOpen)

<Toaster
  position="bottom-center"
  offset={{
    bottom: isAnyModalOpen ? "16px" : "102px"
  }}
  mobileOffset={{
    bottom: isAnyModalOpen ? "16px" : "102px"
  }}
/>

Best Practices

  1. Always update global state: When opening or closing any modal, always call setModalOpen() to keep global state in sync
  2. Cleanup on unmount: If a modal component unmounts while open, ensure setModalOpen(false) is called
  3. Use for coordination only: This store should only be used to coordinate UI elements, not to manage individual modal states
  4. Pair with local state: Each modal should maintain its own local open/close state and sync with the global store
const [isModalOpen, setIsModalOpen] = useState(false)
const setGlobalModalOpen = useModalStore(state => state.setModalOpen)

const openModal = () => {
  setIsModalOpen(true)
  setGlobalModalOpen(true)
}

const closeModal = () => {
  setIsModalOpen(false)
  setGlobalModalOpen(false)
}

Build docs developers (and LLMs) love