Home > Mobile >  How to manually close an overlay?
How to manually close an overlay?

Time:09-18

I'm using enter image description here

Popover JSX

  const [isOpen, setIsOpen] = useState(false);

{snipsData.map((snip, index) => (
 <div key={index} className="hoverable-item flex gap-2">

  //....

  <Popover placement="top" isOpen={isOpen} onOpenChange={setIsOpen}>
  //Pop.Trigger Button sets isOpen to true 
    <Popover.Trigger>
      <Button auto light>
        <DeleteDocumentIcon
          fill="#F31260"
          className="cursor-pointer"
          width={26}
          height={26}
        />
      </Button>
    </Popover.Trigger>
    <Popover.Content>
      <DeleteUser
        snip={snip}
        handleDelete={handleDelete}
        setIsOpen={setIsOpen}
      />
    </Popover.Content>
  </Popover>
 </div>
))}

Overlay buttons in <DeleteUser />

<Grid>
  <Button size="sm" light onClick={() => setIsOpen(false)}>
    Cancel
  </Button>
</Grid>
<Grid>
  <Button
    size="sm"
    shadow
    color="error"
    onClick={() => handleDelete(snip.id)}
  >
    Delete
  </Button>
</Grid>

CodePudding user response:

Okay, so the problem is that you're using a binary state (isOpen) to represent something with more than binary state-- namely, the isOpen state of every snip.

There are a few ways to do this, but I personally like having the state be an object containing a mapping from index => boolean

const [allOpenStates, setAllOpenStates] = useState({});
// in this case, we'll have an object that maps from an
// index to a boolean
// the default state is closed, so a missing value in the map
// will get interpreted as false

{snipsData.map((snip, index) => (
 <div key={index} className="hoverable-item flex gap-2">

  //....

  <Popover placement="top" 
       isOpen={allOpenStates[index]} // it will be undefined if it hasn't ever been opened, which is fine, since undefined is falsey
       onOpenChange={nowOpen => setAllOpenStates(oldState => {...oldState, [index]: nowOpen} )}>

  //Pop.Trigger Button sets allOpenStates[index] = true
    <Popover.Trigger>
      <Button auto light>
        <DeleteDocumentIcon
          fill="#F31260"
          className="cursor-pointer"
          width={26}
          height={26}
        />
      </Button>
    </Popover.Trigger>
    <Popover.Content>
      <DeleteUser
        snip={snip}
        handleDelete={handleDelete}
        setIsOpen={setIsOpen}
      />
    </Popover.Content>
  </Popover>
 </div>
))}

I'm doing this without trying it myself, so some of the syntax may be off. But the general idea is that you need to keep track of the open state for each index, and use that individual index's state for determining if the popover is open and how to handle open/close events.

Another solution would be using a Set of numbers (the index values), where Set membership indicates that the popover is open. Opening the popover would add that index to the set, and closing would remove from the set.This would require some ugly code though, since set operations are mutating.

  • Related