fix: handle shift tab tab-index focus (#6554)

* handle shift tab tab-index focus

* add comment

* fix double tap

* make label focus

* fix title focus

* focus discard and save

* remove comment
This commit is contained in:
Vipin Chaudhary 2025-02-08 20:54:23 +05:30 committed by GitHub
parent feb88e64a4
commit 14083ea7da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 71 additions and 63 deletions

View file

@ -51,6 +51,10 @@ export const ListKeymap = ({ tabIndex }: { tabIndex?: number }) =>
} else if (this.editor.commands.liftListItem("taskItem")) { } else if (this.editor.commands.liftListItem("taskItem")) {
return true; return true;
} }
// if tabIndex is set, we don't want to handle Tab key
if (tabIndex !== undefined && tabIndex !== null) {
return false;
}
return true; return true;
}, },
Delete: ({ editor }) => { Delete: ({ editor }) => {

View file

@ -90,6 +90,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
)} )}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
{button} {button}
</button> </button>
@ -107,6 +108,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
)} )}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
<DropdownButton <DropdownButton
className={buttonClassName} className={buttonClassName}
@ -134,7 +136,6 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
<ComboDropDown <ComboDropDown
as="div" as="div"
ref={dropdownRef} ref={dropdownRef}
tabIndex={tabIndex}
className={cn("h-full", className)} className={cn("h-full", className)}
value={value} value={value}
onChange={dropdownOnChange} onChange={dropdownOnChange}

View file

@ -113,6 +113,7 @@ export const MemberDropdown: React.FC<Props> = observer((props) => {
className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)} className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
{button} {button}
</button> </button>
@ -130,6 +131,7 @@ export const MemberDropdown: React.FC<Props> = observer((props) => {
)} )}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
<DropdownButton <DropdownButton
className={cn("text-xs", buttonClassName)} className={cn("text-xs", buttonClassName)}
@ -161,7 +163,6 @@ export const MemberDropdown: React.FC<Props> = observer((props) => {
<ComboDropDown <ComboDropDown
as="div" as="div"
ref={dropdownRef} ref={dropdownRef}
tabIndex={tabIndex}
className={cn("h-full", className)} className={cn("h-full", className)}
onChange={dropdownOnChange} onChange={dropdownOnChange}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}

View file

@ -239,6 +239,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
)} )}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
{button} {button}
</button> </button>
@ -256,6 +257,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
)} )}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
<DropdownButton <DropdownButton
className={buttonClassName} className={buttonClassName}
@ -296,7 +298,6 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
<ComboDropDown <ComboDropDown
as="div" as="div"
ref={dropdownRef} ref={dropdownRef}
tabIndex={tabIndex}
className={cn("h-full", className)} className={cn("h-full", className)}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
button={comboButton} button={comboButton}

View file

@ -394,6 +394,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)} className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
{button} {button}
</button> </button>
@ -411,6 +412,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
)} )}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
<ButtonToRender <ButtonToRender
priority={value ?? undefined} priority={value ?? undefined}
@ -435,7 +437,6 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
<ComboDropDown <ComboDropDown
as="div" as="div"
ref={dropdownRef} ref={dropdownRef}
tabIndex={tabIndex}
className={cn( className={cn(
"h-full", "h-full",
{ {

View file

@ -141,11 +141,13 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)} className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)}
onClick={handleOnClick} onClick={handleOnClick}
disabled={disabled} disabled={disabled}
tabIndex={tabIndex}
> >
{button} {button}
</button> </button>
) : ( ) : (
<button <button
tabIndex={tabIndex}
ref={setReferenceElement} ref={setReferenceElement}
type="button" type="button"
className={cn( className={cn(
@ -197,7 +199,6 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
<ComboDropDown <ComboDropDown
as="div" as="div"
ref={dropdownRef} ref={dropdownRef}
tabIndex={tabIndex}
className={cn("h-full", className)} className={cn("h-full", className)}
value={stateValue} value={stateValue}
onChange={dropdownOnChange} onChange={dropdownOnChange}

View file

@ -37,7 +37,7 @@ export const IssueTitleInput: React.FC<TIssueTitleInputProps> = observer((props)
return undefined; return undefined;
}; };
return ( return (
<> <div tabIndex={getIndex("name")}>
<Controller <Controller
control={control} control={control}
name="name" name="name"
@ -63,12 +63,11 @@ export const IssueTitleInput: React.FC<TIssueTitleInputProps> = observer((props)
hasError={Boolean(errors.name)} hasError={Boolean(errors.name)}
placeholder={t("title")} placeholder={t("title")}
className="w-full text-base" className="w-full text-base"
tabIndex={getIndex("name")}
autoFocus autoFocus
/> />
)} )}
/> />
<span className="text-xs font-medium text-red-500">{errors?.name?.message}</span> <span className="text-xs font-medium text-red-500">{errors?.name?.message}</span>
</> </div>
); );
}); });

View file

@ -485,7 +485,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
setSelectedParentIssue={setSelectedParentIssue} setSelectedParentIssue={setSelectedParentIssue}
/> />
</div> </div>
<div className="flex items-center justify-end gap-4 py-3"> <div className="flex items-center justify-end gap-4 py-3" tabIndex={getIndex("create_more")}>
{!data?.id && ( {!data?.id && (
<div <div
className="inline-flex items-center gap-1.5 cursor-pointer" className="inline-flex items-center gap-1.5 cursor-pointer"
@ -493,7 +493,6 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === "Enter") onCreateMoreToggleChange(!isCreateMoreToggleEnabled); if (e.key === "Enter") onCreateMoreToggleChange(!isCreateMoreToggleEnabled);
}} }}
tabIndex={getIndex("create_more")}
role="button" role="button"
> >
<ToggleSwitch value={isCreateMoreToggleEnabled} onChange={() => {}} size="sm" /> <ToggleSwitch value={isCreateMoreToggleEnabled} onChange={() => {}} size="sm" />
@ -501,34 +500,37 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
</div> </div>
)} )}
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button <div tabIndex={getIndex("discard_button")}>
variant="neutral-primary" <Button
size="sm" variant="neutral-primary"
onClick={() => { size="sm"
if (editorRef.current?.isEditorReadyToDiscard()) { onClick={() => {
onClose(); if (editorRef.current?.isEditorReadyToDiscard()) {
} else { onClose();
setToast({ } else {
type: TOAST_TYPE.ERROR, setToast({
title: "Error!", type: TOAST_TYPE.ERROR,
message: "Editor is still processing changes. Please wait before proceeding.", title: "Error!",
}); message: "Editor is still processing changes. Please wait before proceeding.",
} });
}} }
tabIndex={getIndex("discard_button")} }}
> >
{t("discard")} {t("discard")}
</Button> </Button>
<Button </div>
variant={moveToIssue ? "neutral-primary" : "primary"} <div tabIndex={isDraft ? getIndex("submit_button") : getIndex("draft_button")}>
type="submit" <Button
size="sm" variant={moveToIssue ? "neutral-primary" : "primary"}
ref={submitBtnRef} type="submit"
loading={isSubmitting} size="sm"
tabIndex={isDraft ? getIndex("submit_button") : getIndex("draft_button")} ref={submitBtnRef}
> loading={isSubmitting}
{isSubmitting ? primaryButtonText.loading : primaryButtonText.default} >
</Button> {isSubmitting ? primaryButtonText.loading : primaryButtonText.default}
</Button>
</div>
{moveToIssue && ( {moveToIssue && (
<Button <Button
variant="primary" variant="primary"

View file

@ -112,31 +112,29 @@ export const IssueLabelSelect: React.FC<Props> = observer((props) => {
disabled={disabled} disabled={disabled}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
> >
<Combobox.Button as={Fragment}> <button
<button type="button"
type="button" ref={setReferenceElement}
ref={setReferenceElement} className={cn("h-full flex cursor-pointer items-center gap-2 text-xs text-custom-text-200", buttonClassName)}
className={cn("h-full flex cursor-pointer items-center gap-2 text-xs text-custom-text-200", buttonClassName)} onClick={handleOnClick}
onClick={handleOnClick} >
> {label ? (
{label ? ( label
label ) : value && value.length > 0 ? (
) : value && value.length > 0 ? ( <span className="flex items-center justify-center gap-2 text-xs h-full">
<span className="flex items-center justify-center gap-2 text-xs h-full"> <IssueLabelsList
<IssueLabelsList labels={value.map((v) => projectLabels?.find((l) => l.id === v)) ?? []}
labels={value.map((v) => projectLabels?.find((l) => l.id === v)) ?? []} length={3}
length={3} showLength
showLength />
/> </span>
</span> ) : (
) : ( <div className="h-full flex items-center justify-center gap-1 rounded border-[0.5px] border-custom-border-300 px-2 py-1 text-xs hover:bg-custom-background-80">
<div className="h-full flex items-center justify-center gap-1 rounded border-[0.5px] border-custom-border-300 px-2 py-1 text-xs hover:bg-custom-background-80"> <Tag className="h-3 w-3 flex-shrink-0" />
<Tag className="h-3 w-3 flex-shrink-0" /> <span>{t("labels")}</span>
<span>{t("labels")}</span> </div>
</div> )}
)} </button>
</button>
</Combobox.Button>
{isDropdownOpen && ( {isDropdownOpen && (
<Combobox.Options className="fixed z-10" static> <Combobox.Options className="fixed z-10" static>