feat: added floating toolbar on text selection (#378)

style: re-designed create-issue modal
This commit is contained in:
Dakshesh Jain 2023-03-06 22:49:06 +05:30 committed by GitHub
parent d28fe930a6
commit 82f8b6d387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 86 additions and 39 deletions

View File

@ -21,6 +21,7 @@ import { CreateUpdateCycleModal } from "components/cycles";
import { CreateLabelModal } from "components/labels"; import { CreateLabelModal } from "components/labels";
// ui // ui
import { Button, CustomMenu, Input, Loader } from "components/ui"; import { Button, CustomMenu, Input, Loader } from "components/ui";
import { PrimaryButton } from "components/ui/button/primary-button";
// icons // icons
import { XMarkIcon } from "@heroicons/react/24/outline"; import { XMarkIcon } from "@heroicons/react/24/outline";
// helpers // 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 {status ? "Update" : "Create"} Issue
</h3> </h3>
</div> </div>
@ -189,11 +190,11 @@ export const IssueForm: FC<IssueFormProps> = ({
<div> <div>
<Input <Input
id="name" id="name"
label="Title"
name="name" name="name"
onChange={handleTitleChange} onChange={handleTitleChange}
className="resize-none" className="resize-none text-xl"
placeholder="Enter title" placeholder="Title"
mode="transparent"
autoComplete="off" autoComplete="off"
error={errors.name} error={errors.name}
register={register} register={register}
@ -219,7 +220,7 @@ export const IssueForm: FC<IssueFormProps> = ({
</span> </span>
? ?
</a> </a>
</Link>{" "} </Link>
</p> </p>
<button <button
type="button" type="button"
@ -234,9 +235,6 @@ export const IssueForm: FC<IssueFormProps> = ({
)} )}
</div> </div>
<div> <div>
<label htmlFor={"description"} className="mb-2 text-gray-500">
Description
</label>
<Controller <Controller
name="description" name="description"
control={control} control={control}
@ -245,7 +243,7 @@ export const IssueForm: FC<IssueFormProps> = ({
value={value} value={value}
onJSONChange={(jsonValue) => setValue("description", jsonValue)} onJSONChange={(jsonValue) => setValue("description", jsonValue)}
onHTMLChange={(htmlValue) => setValue("description_html", htmlValue)} 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>
</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 <div
className="flex cursor-pointer items-center gap-1" className="flex cursor-pointer items-center gap-1"
onClick={() => setCreateMore((prevData) => !prevData)} onClick={() => setCreateMore((prevData) => !prevData)}
@ -360,15 +358,15 @@ export const IssueForm: FC<IssueFormProps> = ({
<Button type="button" theme="secondary" onClick={handleClose}> <Button type="button" theme="secondary" onClick={handleClose}>
Discard Discard
</Button> </Button>
<Button type="submit" disabled={isSubmitting}> <PrimaryButton type="submit" size="sm" loading={isSubmitting}>
{status {status
? isSubmitting ? isSubmitting
? "Updating Issue..." ? "Updating Issue..."
: "Update Issue" : "Update Issue"
: isSubmitting : isSubmitting
? "Creating Issue..." ? "Adding Issue..."
: "Create Issue"} : "Add Issue"}
</Button> </PrimaryButton>
</div> </div>
</div> </div>
</form> </form>

View File

@ -231,7 +231,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
</Transition.Child> </Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto"> <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 <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"

View File

@ -185,7 +185,9 @@ export const SingleProjectCard: React.FC<ProjectCardProps> = ({
</span> </span>
)} )}
</div> </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> </a>
</Link> </Link>
<div className="flex h-full items-end justify-between"> <div className="flex h-full items-end justify-between">

View File

@ -34,9 +34,8 @@ import fileService from "services/file.service";
// ui // ui
import { Spinner } from "components/ui"; import { Spinner } from "components/ui";
// components // components
import { RichTextToolbar } from "./toolbar"; import { CustomFloatingToolbar } from "./toolbar/float-tool-tip";
import { MentionAutoComplete } from "./mention-autocomplete"; import { MentionAutoComplete } from "./mention-autocomplete";
import { FloatingLinkToolbar } from "./toolbar/link";
export interface IRemirrorRichTextEditor { export interface IRemirrorRichTextEditor {
placeholder?: string; placeholder?: string;
@ -51,6 +50,9 @@ export interface IRemirrorRichTextEditor {
customClassName?: string; customClassName?: string;
} }
// eslint-disable-next-line no-duplicate-imports
import { FloatingWrapper, FloatingToolbar } from "@remirror/react";
const RemirrorRichTextEditor: FC<IRemirrorRichTextEditor> = (props) => { const RemirrorRichTextEditor: FC<IRemirrorRichTextEditor> = (props) => {
const { const {
placeholder, placeholder,
@ -182,30 +184,42 @@ const RemirrorRichTextEditor: FC<IRemirrorRichTextEditor> = (props) => {
<Remirror <Remirror
manager={manager} manager={manager}
initialContent={state} 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} editable={editable}
onBlur={() => { onBlur={() => {
onBlur(jsonValue, htmlValue); onBlur(jsonValue, htmlValue);
}} }}
> >
<div className="rounded-md border"> {(!value || value === "" || value?.content?.[0]?.content === undefined) && (
{showToolbar && editable && ( <p className="pointer-events-none absolute top-[8.8rem] left-9 text-gray-300">
<div className="box-border w-full border-b py-2"> {placeholder || "Enter text..."}
<RichTextToolbar /> </p>
</div> )}
)} <EditorComponent />
<EditorComponent />
{imageLoader && ( {imageLoader && (
<div className="p-4"> <div className="p-4">
<Spinner /> <Spinner />
</div> </div>
)} )}
{/* <TableComponents /> */}
<FloatingLinkToolbar /> {editable && (
<MentionAutoComplete mentions={mentions} tags={tags} /> <FloatingWrapper
{<OnChangeJSON onChange={handleJSONChange} />} positioner="always"
{<OnChangeHTML onChange={handleHTMLChange} />} floatingLabel="Custom Floating Toolbar"
</div> renderOutsideEditor
>
<FloatingToolbar className="z-[9999] overflow-hidden rounded">
<CustomFloatingToolbar />
</FloatingToolbar>
</FloatingWrapper>
)}
<MentionAutoComplete mentions={mentions} tags={tags} />
{<OnChangeJSON onChange={handleJSONChange} />}
{<OnChangeHTML onChange={handleHTMLChange} />}
</Remirror> </Remirror>
</div> </div>
); );

View File

@ -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>
);

View File

@ -173,12 +173,12 @@ export const FloatingLinkToolbar = () => {
return ( return (
<> <>
{!isEditing && ( {!isEditing && (
<FloatingToolbar className="shadow-lg rounded bg-white p-1"> <FloatingToolbar className="rounded bg-white p-1 shadow-lg">
{linkEditButtons} {linkEditButtons}
</FloatingToolbar> </FloatingToolbar>
)} )}
{!isEditing && empty && ( {!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} {linkEditButtons}
</FloatingToolbar> </FloatingToolbar>
)} )}