Skip to content

Commit

Permalink
fix popover behaviour with useClickAway
Browse files Browse the repository at this point in the history
  • Loading branch information
Southclaws committed Dec 27, 2023
1 parent 6c92c1e commit 7811ca7
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 12 deletions.
18 changes: 8 additions & 10 deletions web/src/components/thread/ReactList/ReactList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PlusIcon } from "@heroicons/react/24/outline";
import { Button } from "src/theme/components/Button";
import {
Popover,
PopoverAnchor,
PopoverContent,
PopoverPositioner,
PopoverTrigger,
Expand All @@ -15,7 +16,7 @@ import { styled } from "@/styled-system/jsx";
import { Props, useReactList } from "./useReactList";

export function ReactList(props: Props) {
const { authenticated, handlers } = useReactList(props);
const { authenticated, ref, isOpen, handlers } = useReactList(props);
return (
<styled.ul
display="flex"
Expand All @@ -33,19 +34,16 @@ export function ReactList(props: Props) {
))}

{authenticated && (
<Popover lazyMount>
<PopoverTrigger asChild>
<Button size="xs" aria-label="add">
<Popover open={isOpen} lazyMount closeOnInteractOutside={false}>
<PopoverAnchor>
<Button size="xs" aria-label="add" onClick={handlers.handleTrigger}>
<PlusIcon width="1.25em" />
</Button>
</PopoverTrigger>
</PopoverAnchor>

<PopoverPositioner>
<PopoverPositioner ref={ref}>
<PopoverContent>
<Picker
data={data} //
onEmojiSelect={handlers.onSelect}
/>
<Picker data={data} onEmojiSelect={handlers.handleSelect} />
</PopoverContent>
</PopoverPositioner>
</Popover>
Expand Down
28 changes: 26 additions & 2 deletions web/src/components/thread/ReactList/useReactList.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useClickAway } from "@uidotdev/usehooks";
import { mutate } from "swr";

import { postReactAdd } from "src/api/openapi/posts";
import { PostProps } from "src/api/openapi/schemas";
import { getThreadGetKey } from "src/api/openapi/threads";
import { useSession } from "src/auth";
import { useDisclosure } from "src/utils/useDisclosure";

export type Props = PostProps & {
slug?: string;
Expand All @@ -17,15 +19,37 @@ export function useReactList(props: Props) {
const account = useSession();
const authenticated = !!account;

async function onSelect(event: EmojiSelectEvent) {
const { onOpen, onClose, isOpen } = useDisclosure();
const ref = useClickAway<HTMLDivElement>(() => {
onClose();
});

async function handleSelect(event: EmojiSelectEvent) {
await postReactAdd(props.id, { emoji: event.native });
props.slug && mutate(getThreadGetKey(props.slug));

onClose();
}

function handleTrigger() {
if (!authenticated) {
return;
}

// NOTE: Doesn't currently work to close the popover if it's open, because
// by the time this handler is called, the outside click handler has already
// closed the popover. But... tbh who cares! Very low impact issue to fix...
if (!isOpen) onOpen();
else onClose();
}

return {
authenticated,
isOpen,
ref,
handlers: {
onSelect,
handleTrigger,
handleSelect,
},
};
}

0 comments on commit 7811ca7

Please sign in to comment.