mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
feat: added floating toolbar on text selection (#378)
style: re-designed create-issue modal
This commit is contained in:
parent
d28fe930a6
commit
82f8b6d387
@ -21,6 +21,7 @@ import { CreateUpdateCycleModal } from "components/cycles";
|
||||
import { CreateLabelModal } from "components/labels";
|
||||
// ui
|
||||
import { Button, CustomMenu, Input, Loader } from "components/ui";
|
||||
import { PrimaryButton } from "components/ui/button/primary-button";
|
||||
// icons
|
||||
import { XMarkIcon } from "@heroicons/react/24/outline";
|
||||
// helpers
|
||||
@ -156,7 +157,7 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-900">
|
||||
<h3 className="text-xl font-semibold leading-6 text-gray-900">
|
||||
{status ? "Update" : "Create"} Issue
|
||||
</h3>
|
||||
</div>
|
||||
@ -189,11 +190,11 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
<div>
|
||||
<Input
|
||||
id="name"
|
||||
label="Title"
|
||||
name="name"
|
||||
onChange={handleTitleChange}
|
||||
className="resize-none"
|
||||
placeholder="Enter title"
|
||||
className="resize-none text-xl"
|
||||
placeholder="Title"
|
||||
mode="transparent"
|
||||
autoComplete="off"
|
||||
error={errors.name}
|
||||
register={register}
|
||||
@ -219,7 +220,7 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
</span>
|
||||
?
|
||||
</a>
|
||||
</Link>{" "}
|
||||
</Link>
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
@ -234,9 +235,6 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor={"description"} className="mb-2 text-gray-500">
|
||||
Description
|
||||
</label>
|
||||
<Controller
|
||||
name="description"
|
||||
control={control}
|
||||
@ -245,7 +243,7 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
value={value}
|
||||
onJSONChange={(jsonValue) => setValue("description", jsonValue)}
|
||||
onHTMLChange={(htmlValue) => setValue("description_html", htmlValue)}
|
||||
placeholder="Enter Your Text..."
|
||||
placeholder="Description"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@ -333,7 +331,7 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-5 flex items-center justify-between gap-2">
|
||||
<div className="-mx-5 mt-5 flex items-center justify-between gap-2 border-t px-5 pt-5">
|
||||
<div
|
||||
className="flex cursor-pointer items-center gap-1"
|
||||
onClick={() => setCreateMore((prevData) => !prevData)}
|
||||
@ -360,15 +358,15 @@ export const IssueForm: FC<IssueFormProps> = ({
|
||||
<Button type="button" theme="secondary" onClick={handleClose}>
|
||||
Discard
|
||||
</Button>
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
<PrimaryButton type="submit" size="sm" loading={isSubmitting}>
|
||||
{status
|
||||
? isSubmitting
|
||||
? "Updating Issue..."
|
||||
: "Update Issue"
|
||||
: isSubmitting
|
||||
? "Creating Issue..."
|
||||
: "Create Issue"}
|
||||
</Button>
|
||||
? "Adding Issue..."
|
||||
: "Add Issue"}
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -231,7 +231,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-10 overflow-y-auto">
|
||||
<div className="flex min-h-full items-center justify-center p-4 text-center sm:p-0">
|
||||
<div className="mt-10 flex min-h-full items-start justify-center p-4 text-center sm:p-0 md:mt-20">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="ease-out duration-300"
|
||||
|
@ -185,7 +185,9 @@ export const SingleProjectCard: React.FC<ProjectCardProps> = ({
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="mt-3.5 mb-7">{truncateText(project.description ?? "", 100)}</p>
|
||||
<p className="mt-3.5 mb-7 break-all">
|
||||
{truncateText(project.description ?? "", 100)}
|
||||
</p>
|
||||
</a>
|
||||
</Link>
|
||||
<div className="flex h-full items-end justify-between">
|
||||
|
@ -34,9 +34,8 @@ import fileService from "services/file.service";
|
||||
// ui
|
||||
import { Spinner } from "components/ui";
|
||||
// components
|
||||
import { RichTextToolbar } from "./toolbar";
|
||||
import { CustomFloatingToolbar } from "./toolbar/float-tool-tip";
|
||||
import { MentionAutoComplete } from "./mention-autocomplete";
|
||||
import { FloatingLinkToolbar } from "./toolbar/link";
|
||||
|
||||
export interface IRemirrorRichTextEditor {
|
||||
placeholder?: string;
|
||||
@ -51,6 +50,9 @@ export interface IRemirrorRichTextEditor {
|
||||
customClassName?: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { FloatingWrapper, FloatingToolbar } from "@remirror/react";
|
||||
|
||||
const RemirrorRichTextEditor: FC<IRemirrorRichTextEditor> = (props) => {
|
||||
const {
|
||||
placeholder,
|
||||
@ -182,30 +184,42 @@ const RemirrorRichTextEditor: FC<IRemirrorRichTextEditor> = (props) => {
|
||||
<Remirror
|
||||
manager={manager}
|
||||
initialContent={state}
|
||||
classNames={[`p-4 focus:outline-none ${customClassName}`]}
|
||||
classNames={[
|
||||
`p-4 relative focus:outline-none rounded-md border border-transparent focus:border-theme ${customClassName}`,
|
||||
]}
|
||||
editable={editable}
|
||||
onBlur={() => {
|
||||
onBlur(jsonValue, htmlValue);
|
||||
}}
|
||||
>
|
||||
<div className="rounded-md border">
|
||||
{showToolbar && editable && (
|
||||
<div className="box-border w-full border-b py-2">
|
||||
<RichTextToolbar />
|
||||
</div>
|
||||
)}
|
||||
<EditorComponent />
|
||||
{imageLoader && (
|
||||
<div className="p-4">
|
||||
<Spinner />
|
||||
</div>
|
||||
)}
|
||||
{/* <TableComponents /> */}
|
||||
<FloatingLinkToolbar />
|
||||
<MentionAutoComplete mentions={mentions} tags={tags} />
|
||||
{<OnChangeJSON onChange={handleJSONChange} />}
|
||||
{<OnChangeHTML onChange={handleHTMLChange} />}
|
||||
</div>
|
||||
{(!value || value === "" || value?.content?.[0]?.content === undefined) && (
|
||||
<p className="pointer-events-none absolute top-[8.8rem] left-9 text-gray-300">
|
||||
{placeholder || "Enter text..."}
|
||||
</p>
|
||||
)}
|
||||
<EditorComponent />
|
||||
|
||||
{imageLoader && (
|
||||
<div className="p-4">
|
||||
<Spinner />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{editable && (
|
||||
<FloatingWrapper
|
||||
positioner="always"
|
||||
floatingLabel="Custom Floating Toolbar"
|
||||
renderOutsideEditor
|
||||
>
|
||||
<FloatingToolbar className="z-[9999] overflow-hidden rounded">
|
||||
<CustomFloatingToolbar />
|
||||
</FloatingToolbar>
|
||||
</FloatingWrapper>
|
||||
)}
|
||||
|
||||
<MentionAutoComplete mentions={mentions} tags={tags} />
|
||||
{<OnChangeJSON onChange={handleJSONChange} />}
|
||||
{<OnChangeHTML onChange={handleHTMLChange} />}
|
||||
</Remirror>
|
||||
</div>
|
||||
);
|
||||
|
@ -0,0 +1,33 @@
|
||||
// buttons
|
||||
import {
|
||||
ToggleBoldButton,
|
||||
ToggleItalicButton,
|
||||
ToggleUnderlineButton,
|
||||
ToggleStrikeButton,
|
||||
ToggleOrderedListButton,
|
||||
ToggleBulletListButton,
|
||||
ToggleCodeButton,
|
||||
} from "@remirror/react";
|
||||
|
||||
import HeadingControls from "./heading-controls";
|
||||
|
||||
export const CustomFloatingToolbar: React.FC = () => (
|
||||
<div className="z-[99999] flex items-center gap-y-2 divide-x rounded border bg-white p-1 px-0.5 shadow-md">
|
||||
<div className="flex items-center gap-x-1 px-2">
|
||||
<HeadingControls />
|
||||
</div>
|
||||
<div className="flex items-center gap-x-1 px-2">
|
||||
<ToggleBoldButton />
|
||||
<ToggleItalicButton />
|
||||
<ToggleUnderlineButton />
|
||||
<ToggleStrikeButton />
|
||||
</div>
|
||||
<div className="flex items-center gap-x-1 px-2">
|
||||
<ToggleOrderedListButton />
|
||||
<ToggleBulletListButton />
|
||||
</div>
|
||||
<div className="flex items-center gap-x-1 px-2">
|
||||
<ToggleCodeButton />
|
||||
</div>
|
||||
</div>
|
||||
);
|
@ -173,12 +173,12 @@ export const FloatingLinkToolbar = () => {
|
||||
return (
|
||||
<>
|
||||
{!isEditing && (
|
||||
<FloatingToolbar className="shadow-lg rounded bg-white p-1">
|
||||
<FloatingToolbar className="rounded bg-white p-1 shadow-lg">
|
||||
{linkEditButtons}
|
||||
</FloatingToolbar>
|
||||
)}
|
||||
{!isEditing && empty && (
|
||||
<FloatingToolbar positioner={linkPositioner} className="shadow-lg rounded bg-white p-1">
|
||||
<FloatingToolbar positioner={linkPositioner} className="rounded bg-white p-1 shadow-lg">
|
||||
{linkEditButtons}
|
||||
</FloatingToolbar>
|
||||
)}
|
||||
|
Loading…
Reference in New Issue
Block a user