Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/07-collaboration/05-comments/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
DefaultThreadStoreAuth,
YjsThreadStore,
} from "@blocknote/core/comments";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { BlockNoteView } from "@blocknote/shadcn";
import "@blocknote/shadcn/style.css";
import { useCreateBlockNote } from "@blocknote/react";
import { YDocProvider, useYDoc, useYjsProvider } from "@y-sweet/react";
import { useMemo, useState } from "react";
Expand Down
5 changes: 5 additions & 0 deletions examples/07-collaboration/05-comments/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@
line-height: 12px;
padding-left: 14px;
}

.bn-thread {
max-height: 200px;
overflow: auto !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
flex-direction: column;
gap: 10px;
max-height: 100%;
min-width: 350px;
width: 0;
}

Expand All @@ -47,11 +48,6 @@
max-width: 700px;
}

.sidebar-comments-main-container .threads-sidebar-section,
.sidebar-comments-main-container .bn-threads-sidebar .bn-thread {
min-width: 0;
}

.sidebar-comments-main-container .settings {
display: flex;
flex-wrap: wrap;
Expand Down
1 change: 1 addition & 0 deletions packages/ariakit/src/comments/Comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const Comment = forwardRef<
actions,
children,
edited,
emojiPickerOpen, // Unused
...rest
} = props;

Expand Down
4 changes: 4 additions & 0 deletions packages/ariakit/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
inset 0 1px 1px 1px var(--shadow);
}

.bn-ak-popover {
z-index: 10000;
}

.bn-toolbar .bn-ak-popover {
gap: 0.5rem;
}
Expand Down
4 changes: 3 additions & 1 deletion packages/mantine/src/blocknoteStyles.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@
}

/* Mantine Popover component base styles */
.bn-mantine .mantine-Popover-dropdown:not(.bn-menu-dropdown) {
.bn-mantine .bn-panel-popover,
.bn-mantine .bn-emoji-picker-popover {
background-color: transparent;
border: none;
border-radius: 0;
box-shadow: none;
display: flex;
padding: 0;
}

Expand Down
7 changes: 3 additions & 4 deletions packages/mantine/src/comments/Comment.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { assertEmpty } from "@blocknote/core";
import { ComponentProps, mergeRefs, useDictionary } from "@blocknote/react";
import { Avatar, Group, Skeleton, Text } from "@mantine/core";
import { useFocusWithin, useHover } from "@mantine/hooks";
import { useHover } from "@mantine/hooks";
import { forwardRef } from "react";

const AuthorInfo = forwardRef<
Expand Down Expand Up @@ -59,12 +59,12 @@ export const Comment = forwardRef<
timeString,
edited,
actions,
emojiPickerOpen,
children,
...rest
} = props;

const { hovered, ref: hoverRef } = useHover();
const { focused, ref: focusRef } = useFocusWithin();
const mergedRef = mergeRefs([ref, hoverRef]);
assertEmpty(rest, false);

Expand All @@ -73,13 +73,12 @@ export const Comment = forwardRef<
(showActions === true ||
showActions === undefined ||
(showActions === "hover" && hovered) ||
focused);
emojiPickerOpen);

return (
<Group pos="relative" ref={mergedRef} className={className}>
{doShowActions ? (
<Group
ref={focusRef}
style={{
position: "absolute",
right: 0,
Expand Down
8 changes: 7 additions & 1 deletion packages/mantine/src/popover/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ export const Popover = (
assertEmpty(rest);

return (
<MantinePopover withinPortal={false} opened={opened} position={position}>
<MantinePopover
middlewares={{ size: { padding: 20 } }}
withinPortal={false}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewlipski only seeing this now, but can't we use withinPortal instead of using our own createPortal?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically yes, functionally it is the same. However, since we only use a portal for the emoji picker, and neither Ariakit nor ShadCN have popover options to render in a portal, I decided to go with this approach as it's less code and easier to maintain.

opened={opened}
position={position}
zIndex={10000}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer more reasonable values for z-index, but I've not seen what this is compared to

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each of the UI elements is a multiple of 1000 (1000 for side menu, 3000 for formatting toolbar, etc), so this is continuing that pattern.

>
{children}
</MantinePopover>
);
Expand Down
4 changes: 4 additions & 0 deletions packages/react/src/components/Comments/Comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export const Comment = ({
const Components = useComponentsContext()!;

const [isEditing, setEditing] = useState(false);
const [emojiPickerOpen, setEmojiPickerOpen] = useState(false);

if (!editor.comments) {
throw new Error("Comments plugin not found");
Expand Down Expand Up @@ -166,6 +167,7 @@ export const Comment = ({
onEmojiSelect={(emoji: { native: string }) =>
onReactionSelect(emoji.native)
}
onOpenChange={(open) => setEmojiPickerOpen(open)}
>
<Components.Generic.Toolbar.Button
key={"add-reaction"}
Expand Down Expand Up @@ -250,6 +252,7 @@ export const Comment = ({
showActions={"hover"}
actions={actions}
className={"bn-thread-comment"}
emojiPickerOpen={emojiPickerOpen}
>
<CommentEditor
autoFocus={isEditing}
Expand Down Expand Up @@ -279,6 +282,7 @@ export const Comment = ({
onEmojiSelect={(emoji: { native: string }) =>
onReactionSelect(emoji.native)
}
onOpenChange={(open) => setEmojiPickerOpen(open)}
>
<Components.Generic.Badge.Root
className={mergeCSSClasses(
Expand Down
37 changes: 26 additions & 11 deletions packages/react/src/components/Comments/EmojiPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ import { ReactNode, useState } from "react";
import { useComponentsContext } from "../../editor/ComponentsContext.js";
import { useBlockNoteContext } from "../../editor/BlockNoteContext.js";
import Picker from "./EmojiMartPicker.js";
import { createPortal } from "react-dom";
import { useBlockNoteEditor } from "../../hooks/useBlockNoteEditor.js";

export const EmojiPicker = (props: {
onEmojiSelect: (emoji: { native: string }) => void;
onOpenChange?: (open: boolean) => void;
children: ReactNode;
}) => {
const [open, setOpen] = useState(false);

const Components = useComponentsContext()!;
const editor = useBlockNoteEditor();
const blockNoteContext = useBlockNoteContext();

return (
Expand All @@ -24,6 +28,7 @@ export const EmojiPicker = (props: {
event.preventDefault();
event.stopPropagation();
setOpen(!open);
props.onOpenChange?.(!open);
}}
style={{
display: "flex",
Expand All @@ -34,17 +39,27 @@ export const EmojiPicker = (props: {
{props.children}
</div>
</Components.Generic.Popover.Trigger>
<Components.Generic.Popover.Content variant={"panel-popover"}>
<Picker
perLine={7}
onClickOutside={() => setOpen(false)}
onEmojiSelect={(emoji: { native: string }) => {
props.onEmojiSelect(emoji);
setOpen(false);
}}
theme={blockNoteContext?.colorSchemePreference}
/>
</Components.Generic.Popover.Content>
{createPortal(
<Components.Generic.Popover.Content
className={"bn-emoji-picker-popover"}
variant={"panel-popover"}
>
<Picker
perLine={7}
onClickOutside={() => {
setOpen(false);
props.onOpenChange?.(false);
}}
onEmojiSelect={(emoji: { native: string }) => {
props.onEmojiSelect(emoji);
setOpen(false);
props.onOpenChange?.(false);
}}
theme={blockNoteContext?.colorSchemePreference}
/>
</Components.Generic.Popover.Content>,
editor.domElement!.parentElement!,
)}
</Components.Generic.Popover.Root>
);
};
1 change: 1 addition & 0 deletions packages/react/src/editor/ComponentsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ export type ComponentProps = {
edited: boolean;
actions?: ReactNode;
showActions?: boolean | "hover";
emojiPickerOpen?: boolean;
};
};
// TODO: We should try to make everything as generic as we can
Expand Down
6 changes: 6 additions & 0 deletions packages/react/src/editor/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,9 @@
background-color: #20242a;
border: 2px solid #23405b;
}

/* Emoji Picker styling */
em-emoji-picker {
max-height: 100%;
z-index: 11000;
}
1 change: 1 addition & 0 deletions packages/shadcn/src/comments/Comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export const Comment = forwardRef<
timeString,
actions,
edited,
emojiPickerOpen, // Unused
children,
...rest
} = props;
Expand Down
2 changes: 1 addition & 1 deletion packages/shadcn/src/popover/popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const PopoverContent = forwardRef<
sideOffset={8}
className={cn(
className,
"flex flex-col gap-2",
"z-[10000] flex flex-col gap-2",
variant === "panel-popover"
? "w-fit max-w-none border-none p-0 shadow-none"
: "",
Expand Down
Loading