forked from github/plane
[WEB-638] feat: add tabIndex prop support to navigate using Tab key in all the editors (#3902)
* feat: added tab index support to navigate using Tab key in all the editors * chore: changed the name of Table of Contents in Pages * chore: file formatting --------- Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
parent
899771a678
commit
4b30339a59
@ -1,17 +1,28 @@
|
||||
import { Editor, EditorContent } from "@tiptap/react";
|
||||
import { ReactNode } from "react";
|
||||
import { FC, ReactNode } from "react";
|
||||
import { ImageResizer } from "src/ui/extensions/image/image-resize";
|
||||
|
||||
interface EditorContentProps {
|
||||
editor: Editor | null;
|
||||
editorContentCustomClassNames: string | undefined;
|
||||
children?: ReactNode;
|
||||
tabIndex?: number;
|
||||
}
|
||||
|
||||
export const EditorContentWrapper = ({ editor, editorContentCustomClassNames = "", children }: EditorContentProps) => (
|
||||
<div className={`contentEditor ${editorContentCustomClassNames}`}>
|
||||
<EditorContent editor={editor} />
|
||||
{editor?.isActive("image") && editor?.isEditable && <ImageResizer editor={editor} />}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
export const EditorContentWrapper: FC<EditorContentProps> = (props) => {
|
||||
const { editor, editorContentCustomClassNames = "", tabIndex, children } = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`contentEditor ${editorContentCustomClassNames}`}
|
||||
tabIndex={tabIndex}
|
||||
onFocus={() => {
|
||||
editor?.chain().focus(undefined, { scrollIntoView: false }).run();
|
||||
}}
|
||||
>
|
||||
<EditorContent editor={editor} />
|
||||
{editor?.isActive("image") && editor?.isEditable && <ImageResizer editor={editor} />}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -19,7 +19,7 @@ export const ContentBrowser = (props: ContentBrowserProps) => {
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col overflow-hidden">
|
||||
<h2 className="font-medium">Table of Contents</h2>
|
||||
<h2 className="font-medium">Outline</h2>
|
||||
<div className="h-full overflow-y-auto">
|
||||
{markings.length !== 0 ? (
|
||||
markings.map((marking) =>
|
||||
|
@ -29,11 +29,13 @@ type IPageRenderer = {
|
||||
editorContentCustomClassNames?: string;
|
||||
hideDragHandle?: () => void;
|
||||
readonly: boolean;
|
||||
tabIndex?: number;
|
||||
};
|
||||
|
||||
export const PageRenderer = (props: IPageRenderer) => {
|
||||
const {
|
||||
documentDetails,
|
||||
tabIndex,
|
||||
editor,
|
||||
editorClassNames,
|
||||
editorContentCustomClassNames,
|
||||
@ -169,7 +171,11 @@ export const PageRenderer = (props: IPageRenderer) => {
|
||||
)}
|
||||
<div className="flex relative h-full w-full flex-col pr-5 editor-renderer" onMouseOver={handleLinkHover}>
|
||||
<EditorContainer hideDragHandle={hideDragHandle} editor={editor} editorClassNames={editorClassNames}>
|
||||
<EditorContentWrapper editor={editor} editorContentCustomClassNames={editorContentCustomClassNames} />
|
||||
<EditorContentWrapper
|
||||
tabIndex={tabIndex}
|
||||
editor={editor}
|
||||
editorContentCustomClassNames={editorContentCustomClassNames}
|
||||
/>
|
||||
</EditorContainer>
|
||||
</div>
|
||||
{isOpen && linkViewProps && coordinates && (
|
||||
|
@ -47,6 +47,8 @@ interface IDocumentEditor {
|
||||
duplicationConfig?: IDuplicationConfig;
|
||||
pageLockConfig?: IPageLockConfig;
|
||||
pageArchiveConfig?: IPageArchiveConfig;
|
||||
|
||||
tabIndex?: number;
|
||||
}
|
||||
interface DocumentEditorProps extends IDocumentEditor {
|
||||
forwardedRef?: React.Ref<EditorHandle>;
|
||||
@ -79,6 +81,7 @@ const DocumentEditor = ({
|
||||
cancelUploadImage,
|
||||
onActionCompleteHandler,
|
||||
rerenderOnPropsChange,
|
||||
tabIndex,
|
||||
}: IDocumentEditor) => {
|
||||
const { markings, updateMarkings } = useEditorMarkings();
|
||||
const [sidePeekVisible, setSidePeekVisible] = useState(true);
|
||||
@ -160,6 +163,7 @@ const DocumentEditor = ({
|
||||
</div>
|
||||
<div className="h-full w-full md:w-[calc(100%-14rem)] lg:w-[calc(100%-18rem-18rem)] page-renderer">
|
||||
<PageRenderer
|
||||
tabIndex={tabIndex}
|
||||
onActionCompleteHandler={onActionCompleteHandler}
|
||||
hideDragHandle={hideDragHandleOnMouseLeave}
|
||||
readonly={false}
|
||||
|
@ -28,6 +28,7 @@ interface IDocumentReadOnlyEditor {
|
||||
message: string;
|
||||
type: "success" | "error" | "warning" | "info";
|
||||
}) => void;
|
||||
tabIndex?: number;
|
||||
}
|
||||
|
||||
interface DocumentReadOnlyEditorProps extends IDocumentReadOnlyEditor {
|
||||
@ -51,6 +52,7 @@ const DocumentReadOnlyEditor = ({
|
||||
pageArchiveConfig,
|
||||
rerenderOnPropsChange,
|
||||
onActionCompleteHandler,
|
||||
tabIndex,
|
||||
}: DocumentReadOnlyEditorProps) => {
|
||||
const router = useRouter();
|
||||
const [sidePeekVisible, setSidePeekVisible] = useState(true);
|
||||
@ -108,6 +110,7 @@ const DocumentReadOnlyEditor = ({
|
||||
</div>
|
||||
<div className="h-full w-[calc(100%-14rem)] lg:w-[calc(100%-18rem-18rem)] page-renderer">
|
||||
<PageRenderer
|
||||
tabIndex={tabIndex}
|
||||
onActionCompleteHandler={onActionCompleteHandler}
|
||||
updatePageTitle={() => Promise.resolve()}
|
||||
readonly={true}
|
||||
|
@ -42,6 +42,7 @@ interface ILiteTextEditor {
|
||||
mentionHighlights?: string[];
|
||||
mentionSuggestions?: IMentionSuggestion[];
|
||||
submitButton?: React.ReactNode;
|
||||
tabIndex?: number;
|
||||
}
|
||||
|
||||
interface LiteTextEditorProps extends ILiteTextEditor {
|
||||
@ -74,6 +75,7 @@ const LiteTextEditor = (props: LiteTextEditorProps) => {
|
||||
mentionHighlights,
|
||||
mentionSuggestions,
|
||||
submitButton,
|
||||
tabIndex,
|
||||
} = props;
|
||||
|
||||
const editor = useEditor({
|
||||
@ -103,7 +105,11 @@ const LiteTextEditor = (props: LiteTextEditorProps) => {
|
||||
return (
|
||||
<EditorContainer editor={editor} editorClassNames={editorClassNames}>
|
||||
<div className="flex flex-col">
|
||||
<EditorContentWrapper editor={editor} editorContentCustomClassNames={editorContentCustomClassNames} />
|
||||
<EditorContentWrapper
|
||||
tabIndex={tabIndex}
|
||||
editor={editor}
|
||||
editorContentCustomClassNames={editorContentCustomClassNames}
|
||||
/>
|
||||
<div className="mt-4 w-full">
|
||||
<FixedMenu
|
||||
editor={editor}
|
||||
|
@ -8,6 +8,7 @@ interface ICoreReadOnlyEditor {
|
||||
borderOnFocus?: boolean;
|
||||
customClassName?: string;
|
||||
mentionHighlights: string[];
|
||||
tabIndex?: number;
|
||||
}
|
||||
|
||||
interface EditorCoreProps extends ICoreReadOnlyEditor {
|
||||
@ -27,6 +28,7 @@ const LiteReadOnlyEditor = ({
|
||||
value,
|
||||
forwardedRef,
|
||||
mentionHighlights,
|
||||
tabIndex,
|
||||
}: EditorCoreProps) => {
|
||||
const editor = useReadOnlyEditor({
|
||||
value,
|
||||
@ -45,7 +47,11 @@ const LiteReadOnlyEditor = ({
|
||||
return (
|
||||
<EditorContainer editor={editor} editorClassNames={editorClassNames}>
|
||||
<div className="flex flex-col">
|
||||
<EditorContentWrapper editor={editor} editorContentCustomClassNames={editorContentCustomClassNames} />
|
||||
<EditorContentWrapper
|
||||
tabIndex={tabIndex}
|
||||
editor={editor}
|
||||
editorContentCustomClassNames={editorContentCustomClassNames}
|
||||
/>
|
||||
</div>
|
||||
</EditorContainer>
|
||||
);
|
||||
|
@ -36,6 +36,7 @@ export type IRichTextEditor = {
|
||||
debouncedUpdatesEnabled?: boolean;
|
||||
mentionHighlights?: string[];
|
||||
mentionSuggestions?: IMentionSuggestion[];
|
||||
tabIndex?: number;
|
||||
};
|
||||
|
||||
export interface RichTextEditorProps extends IRichTextEditor {
|
||||
@ -68,6 +69,7 @@ const RichTextEditor = ({
|
||||
mentionHighlights,
|
||||
rerenderOnPropsChange,
|
||||
mentionSuggestions,
|
||||
tabIndex,
|
||||
}: RichTextEditorProps) => {
|
||||
const [hideDragHandleOnMouseLeave, setHideDragHandleOnMouseLeave] = React.useState<() => void>(() => {});
|
||||
|
||||
@ -110,7 +112,11 @@ const RichTextEditor = ({
|
||||
<EditorContainer hideDragHandle={hideDragHandleOnMouseLeave} editor={editor} editorClassNames={editorClassNames}>
|
||||
{editor && <EditorBubbleMenu editor={editor} />}
|
||||
<div className="flex flex-col">
|
||||
<EditorContentWrapper editor={editor} editorContentCustomClassNames={editorContentCustomClassNames} />
|
||||
<EditorContentWrapper
|
||||
tabIndex={tabIndex}
|
||||
editor={editor}
|
||||
editorContentCustomClassNames={editorContentCustomClassNames}
|
||||
/>
|
||||
</div>
|
||||
</EditorContainer>
|
||||
);
|
||||
|
@ -9,6 +9,7 @@ interface IRichTextReadOnlyEditor {
|
||||
borderOnFocus?: boolean;
|
||||
customClassName?: string;
|
||||
mentionHighlights?: string[];
|
||||
tabIndex?: number;
|
||||
}
|
||||
|
||||
interface RichTextReadOnlyEditorProps extends IRichTextReadOnlyEditor {
|
||||
|
@ -467,7 +467,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
}}
|
||||
mentionHighlights={mentionHighlights}
|
||||
mentionSuggestions={mentionSuggestions}
|
||||
// tabIndex={2}
|
||||
tabIndex={getTabIndex("description_html")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
Loading…
Reference in New Issue
Block a user