mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fixed bubble menu to match styles and added better seperation in UI
This commit is contained in:
parent
60f1b7346d
commit
50e7c5924c
@ -78,7 +78,7 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
||||
return (
|
||||
<BubbleMenu
|
||||
{...bubbleMenuProps}
|
||||
className="flex w-fit divide-x divide-stone-200 rounded border border-stone-200 bg-white shadow-xl"
|
||||
className="flex w-fit divide-x divide-custom-border-400 rounded border border-custom-text-200 bg-custom-background-100 shadow-xl"
|
||||
>
|
||||
<NodeSelector
|
||||
editor={props.editor}
|
||||
@ -101,7 +101,7 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
||||
<button
|
||||
key={index}
|
||||
onClick={item.command}
|
||||
className="p-2 text-stone-600 hover:bg-stone-100 active:bg-stone-200"
|
||||
className="p-2 text-custom-text-200 hover:bg-custom-background-100 active:bg-custom-background-100 transition-colors"
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-4 w-4", {
|
||||
|
@ -10,10 +10,17 @@ import TaskItem from "@tiptap/extension-task-item";
|
||||
import TaskList from "@tiptap/extension-task-list";
|
||||
import { Markdown } from "tiptap-markdown";
|
||||
import Highlight from "@tiptap/extension-highlight";
|
||||
|
||||
// import SlashCommand from "./slash-command";
|
||||
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
||||
import { lowlight } from 'lowlight/lib/core'
|
||||
import SlashCommand from "./slash-command";
|
||||
import { InputRule } from "@tiptap/core";
|
||||
|
||||
import ts from 'highlight.js/lib/languages/typescript'
|
||||
|
||||
import 'highlight.js/styles/github-dark.css';
|
||||
|
||||
lowlight.registerLanguage('ts', ts)
|
||||
|
||||
export const TiptapExtensions = [
|
||||
StarterKit.configure({
|
||||
bulletList: {
|
||||
@ -36,19 +43,14 @@ export const TiptapExtensions = [
|
||||
class: "border-l-4 border-stone-700",
|
||||
},
|
||||
},
|
||||
codeBlock: {
|
||||
HTMLAttributes: {
|
||||
class:
|
||||
"rounded-sm bg-stone-100 p-5 font-mono font-medium text-stone-800",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
HTMLAttributes: {
|
||||
class:
|
||||
"rounded-md bg-stone-200 px-1.5 py-1 font-mono font-medium text-stone-900",
|
||||
"rounded-md bg-stone-200 px-1 py-1 font-mono font-medium text-stone-900",
|
||||
spellcheck: "false",
|
||||
},
|
||||
},
|
||||
codeBlock: false,
|
||||
horizontalRule: false,
|
||||
dropcursor: {
|
||||
color: "#DBEAFE",
|
||||
@ -56,6 +58,9 @@ export const TiptapExtensions = [
|
||||
},
|
||||
gapcursor: false,
|
||||
}),
|
||||
CodeBlockLowlight.configure({
|
||||
lowlight,
|
||||
}),
|
||||
HorizontalRule.extend({
|
||||
addInputRules() {
|
||||
return [
|
||||
@ -78,7 +83,7 @@ export const TiptapExtensions = [
|
||||
},
|
||||
}).configure({
|
||||
HTMLAttributes: {
|
||||
class: "mt-4 mb-6 border-t border-stone-300",
|
||||
class: "mb-6 border-t border-custom-border-400",
|
||||
},
|
||||
}),
|
||||
TiptapLink.configure({
|
||||
@ -98,11 +103,12 @@ export const TiptapExtensions = [
|
||||
if (node.type.name === "heading") {
|
||||
return `Heading ${node.attrs.level}`;
|
||||
}
|
||||
return "Press '/' for commands, or '++' for AI autocomplete...";
|
||||
|
||||
return "Press '/' for commands, or 'Ctrl + Space' for AI autocomplete...";
|
||||
},
|
||||
includeChildren: true,
|
||||
}),
|
||||
// SlashCommand,
|
||||
SlashCommand,
|
||||
TiptapUnderline,
|
||||
TextStyle,
|
||||
Color,
|
||||
|
@ -16,7 +16,6 @@ export const LinkSelector: FC<LinkSelectorProps> = ({
|
||||
}) => {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// Autofocus on input by default
|
||||
useEffect(() => {
|
||||
inputRef.current && inputRef.current?.focus();
|
||||
});
|
||||
@ -24,14 +23,14 @@ export const LinkSelector: FC<LinkSelectorProps> = ({
|
||||
return (
|
||||
<div className="relative">
|
||||
<button
|
||||
className="flex h-full items-center space-x-2 px-3 py-1.5 text-sm font-medium text-stone-600 hover:bg-stone-100 active:bg-stone-200"
|
||||
className="flex h-full items-center space-x-2 px-3 py-1.5 text-sm font-medium text-custom-text-200 hover:bg-custom-background-80 active:bg-custom-background-80"
|
||||
onClick={() => {
|
||||
setIsOpen(!isOpen);
|
||||
}}
|
||||
>
|
||||
<p className="text-base">↗</p>
|
||||
<p
|
||||
className={cn("underline decoration-stone-400 underline-offset-4", {
|
||||
className={cn("underline underline-offset-4", {
|
||||
"text-blue-500": editor.isActive("link"),
|
||||
})}
|
||||
>
|
||||
@ -46,13 +45,13 @@ export const LinkSelector: FC<LinkSelectorProps> = ({
|
||||
editor.chain().focus().setLink({ href: input.value }).run();
|
||||
setIsOpen(false);
|
||||
}}
|
||||
className="fixed top-full z-[99999] mt-1 flex w-60 overflow-hidden rounded border border-stone-200 bg-white p-1 shadow-xl animate-in fade-in slide-in-from-top-1"
|
||||
className="fixed top-full z-[99999] mt-1 flex w-60 overflow-hidden rounded border border-custom-border-100 bg-custom-background-100 dow-xl animate-in fade-in slide-in-from-top-1"
|
||||
>
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="url"
|
||||
placeholder="Paste a link"
|
||||
className="flex-1 bg-white p-1 text-sm outline-none"
|
||||
className="flex-1 bg-custom-background-100 border border-blue-900 p-1 text-sm outline-none"
|
||||
defaultValue={editor.getAttributes("link").href || ""}
|
||||
/>
|
||||
{editor.getAttributes("link").href ? (
|
||||
@ -66,7 +65,7 @@ export const LinkSelector: FC<LinkSelectorProps> = ({
|
||||
<Trash className="h-4 w-4" />
|
||||
</button>
|
||||
) : (
|
||||
<button className="flex items-center rounded-sm p-1 text-stone-600 transition-all hover:bg-stone-100">
|
||||
<button className="flex items-center rounded-sm p-1 text-custom-text-300 transition-all hover:bg-stone-100">
|
||||
<Check className="h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
import { Dispatch, FC, SetStateAction } from "react";
|
||||
|
||||
import { BubbleMenuItem } from "./EditorBubbleMenu";
|
||||
import { cn } from "./utils";
|
||||
|
||||
interface NodeSelectorProps {
|
||||
editor: Editor;
|
||||
@ -32,26 +33,25 @@ export const NodeSelector: FC<NodeSelectorProps> = ({
|
||||
icon: TextIcon,
|
||||
command: () =>
|
||||
editor.chain().focus().toggleNode("paragraph", "paragraph").run(),
|
||||
// I feel like there has to be a more efficient way to do this – feel free to PR if you know how!
|
||||
isActive: () =>
|
||||
editor.isActive("paragraph") &&
|
||||
!editor.isActive("bulletList") &&
|
||||
!editor.isActive("orderedList"),
|
||||
},
|
||||
{
|
||||
name: "Heading 1",
|
||||
name: "H1",
|
||||
icon: Heading1,
|
||||
command: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),
|
||||
isActive: () => editor.isActive("heading", { level: 1 }),
|
||||
},
|
||||
{
|
||||
name: "Heading 2",
|
||||
name: "H2",
|
||||
icon: Heading2,
|
||||
command: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
|
||||
isActive: () => editor.isActive("heading", { level: 2 }),
|
||||
},
|
||||
{
|
||||
name: "Heading 3",
|
||||
name: "H3",
|
||||
icon: Heading3,
|
||||
command: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
|
||||
isActive: () => editor.isActive("heading", { level: 3 }),
|
||||
@ -101,7 +101,7 @@ export const NodeSelector: FC<NodeSelectorProps> = ({
|
||||
return (
|
||||
<div className="relative h-full">
|
||||
<button
|
||||
className="flex h-full items-center gap-1 whitespace-nowrap p-2 text-sm font-medium text-stone-600 hover:bg-stone-100 active:bg-stone-200"
|
||||
className="flex h-full items-center gap-1 whitespace-nowrap p-2 text-sm font-medium text-custom-text-200 hover:bg-custom-background-80 active:bg-custom-background-80"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
<span>{activeItem?.name}</span>
|
||||
@ -109,7 +109,7 @@ export const NodeSelector: FC<NodeSelectorProps> = ({
|
||||
</button>
|
||||
|
||||
{isOpen && (
|
||||
<section className="fixed top-full z-[99999] mt-1 flex w-48 flex-col overflow-hidden rounded border border-stone-200 bg-white p-1 shadow-xl animate-in fade-in slide-in-from-top-1">
|
||||
<section className="fixed top-full z-[99999] mt-1 flex w-48 flex-col overflow-hidden rounded border border-custom-border-200 bg-custom-background-100 p-1 shadow-xl animate-in fade-in slide-in-from-top-1">
|
||||
{items.map((item, index) => (
|
||||
<button
|
||||
key={index}
|
||||
@ -117,10 +117,10 @@ export const NodeSelector: FC<NodeSelectorProps> = ({
|
||||
item.command();
|
||||
setIsOpen(false);
|
||||
}}
|
||||
className="flex items-center justify-between rounded-sm px-2 py-1 text-sm text-stone-600 hover:bg-stone-100"
|
||||
className={cn("flex items-center justify-between rounded-sm px-2 py-1 text-sm text-custom-text-200 hover:bg-gray-800 hover:text-custom-text-100", { "bg-gray-800": activeItem.name === item.name })}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="rounded-sm border border-stone-200 p-1">
|
||||
<div className="rounded-sm border border-custom-border-300 p-1" >
|
||||
<item.icon className="h-3 w-3" />
|
||||
</div>
|
||||
<span>{item.name}</span>
|
||||
@ -129,7 +129,8 @@ export const NodeSelector: FC<NodeSelectorProps> = ({
|
||||
</button>
|
||||
))}
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div >
|
||||
);
|
||||
};
|
||||
|
@ -27,8 +27,10 @@
|
||||
"@nivo/scatterplot": "0.80.0",
|
||||
"@sentry/nextjs": "^7.36.0",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@tiptap/extension-code-block-lowlight": "^2.0.4",
|
||||
"@tiptap/extension-color": "^2.0.4",
|
||||
"@tiptap/extension-highlight": "^2.0.4",
|
||||
"@tiptap/extension-horizontal-rule": "^2.0.4",
|
||||
"@tiptap/extension-image": "^2.0.4",
|
||||
"@tiptap/extension-link": "^2.0.4",
|
||||
"@tiptap/extension-placeholder": "^2.0.4",
|
||||
@ -39,14 +41,17 @@
|
||||
"@tiptap/pm": "^2.0.4",
|
||||
"@tiptap/react": "^2.0.4",
|
||||
"@tiptap/starter-kit": "^2.0.4",
|
||||
"@tiptap/suggestion": "^2.0.4",
|
||||
"@types/lodash.debounce": "^4.0.7",
|
||||
"@types/react-datepicker": "^4.8.0",
|
||||
"axios": "^1.1.3",
|
||||
"clsx": "^2.0.0",
|
||||
"cmdk": "^0.2.0",
|
||||
"dotenv": "^16.0.3",
|
||||
"highlight.js": "^11.8.0",
|
||||
"js-cookie": "^3.0.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lowlight": "^2.9.0",
|
||||
"lucide-react": "^0.263.1",
|
||||
"next": "12.3.2",
|
||||
"next-pwa": "^5.6.0",
|
||||
@ -60,10 +65,13 @@
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-hook-form": "^7.38.0",
|
||||
"react-markdown": "^8.0.7",
|
||||
"sonner": "^0.6.2",
|
||||
"swr": "^2.1.3",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwindcss-animate": "^1.0.6",
|
||||
"tiptap-markdown": "^0.8.2",
|
||||
"tlds": "^1.238.0",
|
||||
"use-debounce": "^9.0.4",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
Loading…
Reference in New Issue
Block a user