[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:
M. Palanikannan 2024-03-11 20:58:23 +05:30 committed by GitHub
parent 899771a678
commit 4b30339a59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 57 additions and 14 deletions

View File

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

View File

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

View File

@ -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 && (

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

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

View File

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

View File

@ -9,6 +9,7 @@ interface IRichTextReadOnlyEditor {
borderOnFocus?: boolean;
customClassName?: string;
mentionHighlights?: string[];
tabIndex?: number;
}
interface RichTextReadOnlyEditorProps extends IRichTextReadOnlyEditor {

View File

@ -467,7 +467,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
}}
mentionHighlights={mentionHighlights}
mentionSuggestions={mentionSuggestions}
// tabIndex={2}
tabIndex={getTabIndex("description_html")}
/>
)}
/>