forked from github/plane
[WEB-512] fix: date inputs keyboard navigation (#3753)
* fix: tab indices logic * fix: due date highlight logic * Revert "fix: due date highlight logic" This reverts commit f523078689e1570295a6067ce4f9580a6a031f22.
This commit is contained in:
parent
27fcfcf620
commit
34f89ba45b
@ -64,6 +64,31 @@ export interface IssueFormProps {
|
|||||||
const aiService = new AIService();
|
const aiService = new AIService();
|
||||||
const fileService = new FileService();
|
const fileService = new FileService();
|
||||||
|
|
||||||
|
const TAB_INDICES = [
|
||||||
|
"name",
|
||||||
|
"description_html",
|
||||||
|
"feeling_lucky",
|
||||||
|
"ai_assistant",
|
||||||
|
"state_id",
|
||||||
|
"priority",
|
||||||
|
"assignee_ids",
|
||||||
|
"label_ids",
|
||||||
|
"start_date",
|
||||||
|
"target_date",
|
||||||
|
"cycle_id",
|
||||||
|
"module_ids",
|
||||||
|
"estimate_point",
|
||||||
|
"parent_id",
|
||||||
|
"create_more",
|
||||||
|
"discard_button",
|
||||||
|
"draft_button",
|
||||||
|
"submit_button",
|
||||||
|
"project_id",
|
||||||
|
"remove_parent",
|
||||||
|
];
|
||||||
|
|
||||||
|
const getTabIndex = (key: string) => TAB_INDICES.findIndex((tabIndex) => tabIndex === key) + 1;
|
||||||
|
|
||||||
export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
@ -271,7 +296,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
}}
|
}}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
// TODO: update tabIndex logic
|
// TODO: update tabIndex logic
|
||||||
tabIndex={19}
|
tabIndex={getTabIndex("project_id")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -294,15 +319,18 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
{selectedParentIssue.project__identifier}-{selectedParentIssue.sequence_id}
|
{selectedParentIssue.project__identifier}-{selectedParentIssue.sequence_id}
|
||||||
</span>
|
</span>
|
||||||
<span className="truncate font-medium">{selectedParentIssue.name.substring(0, 50)}</span>
|
<span className="truncate font-medium">{selectedParentIssue.name.substring(0, 50)}</span>
|
||||||
<X
|
<button
|
||||||
className="h-3 w-3 cursor-pointer"
|
type="button"
|
||||||
|
className="grid place-items-center"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setValue("parent_id", null);
|
setValue("parent_id", null);
|
||||||
handleFormChange();
|
handleFormChange();
|
||||||
setSelectedParentIssue(null);
|
setSelectedParentIssue(null);
|
||||||
}}
|
}}
|
||||||
tabIndex={20}
|
tabIndex={getTabIndex("remove_parent")}
|
||||||
/>
|
>
|
||||||
|
<X className="h-3 w-3 cursor-pointer" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -332,7 +360,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
hasError={Boolean(errors.name)}
|
hasError={Boolean(errors.name)}
|
||||||
placeholder="Issue Title"
|
placeholder="Issue Title"
|
||||||
className="resize-none text-xl w-full"
|
className="resize-none text-xl w-full"
|
||||||
tabIndex={1}
|
tabIndex={getTabIndex("name")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -346,7 +374,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
}`}
|
}`}
|
||||||
onClick={handleAutoGenerateDescription}
|
onClick={handleAutoGenerateDescription}
|
||||||
disabled={iAmFeelingLucky}
|
disabled={iAmFeelingLucky}
|
||||||
tabIndex={3}
|
tabIndex={getTabIndex("feeling_lucky")}
|
||||||
>
|
>
|
||||||
{iAmFeelingLucky ? (
|
{iAmFeelingLucky ? (
|
||||||
"Generating response"
|
"Generating response"
|
||||||
@ -375,7 +403,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="flex items-center gap-1 rounded px-1.5 py-1 text-xs hover:bg-custom-background-90"
|
className="flex items-center gap-1 rounded px-1.5 py-1 text-xs hover:bg-custom-background-90"
|
||||||
onClick={() => setGptAssistantModal((prevData) => !prevData)}
|
onClick={() => setGptAssistantModal((prevData) => !prevData)}
|
||||||
tabIndex={4}
|
tabIndex={getTabIndex("ai_assistant")}
|
||||||
>
|
>
|
||||||
<Sparkle className="h-4 w-4" />
|
<Sparkle className="h-4 w-4" />
|
||||||
AI
|
AI
|
||||||
@ -426,7 +454,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
}}
|
}}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
tabIndex={6}
|
tabIndex={getTabIndex("state_id")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -443,7 +471,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
handleFormChange();
|
handleFormChange();
|
||||||
}}
|
}}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
tabIndex={7}
|
tabIndex={getTabIndex("priority")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -464,7 +492,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
buttonClassName={value?.length > 0 ? "hover:bg-transparent px-0" : ""}
|
buttonClassName={value?.length > 0 ? "hover:bg-transparent px-0" : ""}
|
||||||
placeholder="Assignees"
|
placeholder="Assignees"
|
||||||
multiple
|
multiple
|
||||||
tabIndex={8}
|
tabIndex={getTabIndex("assignee_ids")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -482,7 +510,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
handleFormChange();
|
handleFormChange();
|
||||||
}}
|
}}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
tabIndex={9}
|
tabIndex={getTabIndex("label_ids")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -498,6 +526,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
maxDate={maxDate ?? undefined}
|
maxDate={maxDate ?? undefined}
|
||||||
placeholder="Start date"
|
placeholder="Start date"
|
||||||
|
tabIndex={getTabIndex("start_date")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -513,6 +542,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
minDate={minDate ?? undefined}
|
minDate={minDate ?? undefined}
|
||||||
placeholder="Due date"
|
placeholder="Due date"
|
||||||
|
tabIndex={getTabIndex("target_date")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -531,7 +561,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
}}
|
}}
|
||||||
value={value}
|
value={value}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
tabIndex={11}
|
tabIndex={getTabIndex("cycle_id")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -551,7 +581,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
handleFormChange();
|
handleFormChange();
|
||||||
}}
|
}}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
tabIndex={12}
|
tabIndex={getTabIndex("module_ids")}
|
||||||
multiple
|
multiple
|
||||||
showCount
|
showCount
|
||||||
/>
|
/>
|
||||||
@ -573,7 +603,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
}}
|
}}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
tabIndex={13}
|
tabIndex={getTabIndex("estimate_point")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -603,7 +633,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
placement="bottom-start"
|
placement="bottom-start"
|
||||||
tabIndex={14}
|
tabIndex={getTabIndex("parent_id")}
|
||||||
>
|
>
|
||||||
{watch("parent_id") ? (
|
{watch("parent_id") ? (
|
||||||
<>
|
<>
|
||||||
@ -653,7 +683,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
if (e.key === "Enter") onCreateMoreToggleChange(!isCreateMoreToggleEnabled);
|
if (e.key === "Enter") onCreateMoreToggleChange(!isCreateMoreToggleEnabled);
|
||||||
}}
|
}}
|
||||||
tabIndex={15}
|
tabIndex={getTabIndex("create_more")}
|
||||||
>
|
>
|
||||||
<div className="flex cursor-pointer items-center justify-center">
|
<div className="flex cursor-pointer items-center justify-center">
|
||||||
<ToggleSwitch value={isCreateMoreToggleEnabled} onChange={() => {}} size="sm" />
|
<ToggleSwitch value={isCreateMoreToggleEnabled} onChange={() => {}} size="sm" />
|
||||||
@ -661,7 +691,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
<span className="text-xs">Create more</span>
|
<span className="text-xs">Create more</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Button variant="neutral-primary" size="sm" onClick={onClose} tabIndex={16}>
|
<Button variant="neutral-primary" size="sm" onClick={onClose} tabIndex={getTabIndex("discard_button")}>
|
||||||
Discard
|
Discard
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
@ -673,7 +703,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
size="sm"
|
size="sm"
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
onClick={handleSubmit((data) => handleFormSubmit({ ...data, is_draft: false }))}
|
onClick={handleSubmit((data) => handleFormSubmit({ ...data, is_draft: false }))}
|
||||||
tabIndex={17}
|
tabIndex={getTabIndex("draft_button")}
|
||||||
>
|
>
|
||||||
{isSubmitting ? "Moving" : "Move from draft"}
|
{isSubmitting ? "Moving" : "Move from draft"}
|
||||||
</Button>
|
</Button>
|
||||||
@ -683,7 +713,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
size="sm"
|
size="sm"
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
onClick={handleSubmit((data) => handleFormSubmit(data, true))}
|
onClick={handleSubmit((data) => handleFormSubmit(data, true))}
|
||||||
tabIndex={17}
|
tabIndex={getTabIndex("draft_button")}
|
||||||
>
|
>
|
||||||
{isSubmitting ? "Saving" : "Save as draft"}
|
{isSubmitting ? "Saving" : "Save as draft"}
|
||||||
</Button>
|
</Button>
|
||||||
@ -691,7 +721,13 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button variant="primary" type="submit" size="sm" loading={isSubmitting} tabIndex={isDraft ? 18 : 17}>
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
type="submit"
|
||||||
|
size="sm"
|
||||||
|
loading={isSubmitting}
|
||||||
|
tabIndex={isDraft ? getTabIndex("submit_button") : getTabIndex("draft_button")}
|
||||||
|
>
|
||||||
{data?.id ? (isSubmitting ? "Updating" : "Update issue") : isSubmitting ? "Creating" : "Create issue"}
|
{data?.id ? (isSubmitting ? "Updating" : "Update issue") : isSubmitting ? "Creating" : "Create issue"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user