[PWA-26] chore: pwa input focus improvement (#5507)
* chore: pwa dropdown input focus improvement * chore: tab indices helper function updated and code refactor * chore: modal tab index refactoring * fix: PWA filters input autofocus * chore: intake tab index updated and code refactor * chore: code refactor
This commit is contained in:
parent
c84c37805c
commit
52f78a86af
47 changed files with 430 additions and 125 deletions
|
|
@ -2,8 +2,14 @@ import { ChangeEvent } from "react";
|
|||
import { Controller, useFormContext, UseFormSetValue } from "react-hook-form";
|
||||
import { Info } from "lucide-react";
|
||||
import { cn } from "@plane/editor";
|
||||
// ui
|
||||
import { Input, TextArea, Tooltip } from "@plane/ui";
|
||||
// constants
|
||||
import { ETabIndices } from "@/constants/tab-indices";
|
||||
// helpers
|
||||
import { projectIdentifierSanitizer } from "@/helpers/project.helper";
|
||||
import { getTabIndex } from "@/helpers/tab-indices.helper";
|
||||
// plane-web types
|
||||
import { TProject } from "@/plane-web/types/projects";
|
||||
|
||||
type Props = {
|
||||
|
|
@ -19,6 +25,8 @@ const ProjectCommonAttributes: React.FC<Props> = (props) => {
|
|||
control,
|
||||
} = useFormContext<TProject>();
|
||||
|
||||
const { getIndex } = getTabIndex(ETabIndices.PROJECT_CREATE, isMobile);
|
||||
|
||||
const handleNameChange = (onChange: (...event: any[]) => void) => (e: ChangeEvent<HTMLInputElement>) => {
|
||||
if (!isChangeInIdentifierRequired) {
|
||||
onChange(e);
|
||||
|
|
@ -58,7 +66,7 @@ const ProjectCommonAttributes: React.FC<Props> = (props) => {
|
|||
hasError={Boolean(errors.name)}
|
||||
placeholder="Project name"
|
||||
className="w-full focus:border-blue-400"
|
||||
tabIndex={1}
|
||||
tabIndex={getIndex("name")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
@ -94,7 +102,7 @@ const ProjectCommonAttributes: React.FC<Props> = (props) => {
|
|||
className={cn("w-full text-xs focus:border-blue-400 pr-7", {
|
||||
uppercase: value,
|
||||
})}
|
||||
tabIndex={2}
|
||||
tabIndex={getIndex("identifier")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
@ -121,7 +129,7 @@ const ProjectCommonAttributes: React.FC<Props> = (props) => {
|
|||
onChange={onChange}
|
||||
className="!h-24 text-sm focus:border-blue-400"
|
||||
hasError={Boolean(errors?.description)}
|
||||
tabIndex={3}
|
||||
tabIndex={getIndex("description")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -2,18 +2,26 @@ import { useState } from "react";
|
|||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { X } from "lucide-react";
|
||||
import { IProject } from "@plane/types";
|
||||
// ui
|
||||
import { CustomEmojiIconPicker, EmojiIconPickerTypes, Logo } from "@plane/ui";
|
||||
// components
|
||||
import { ImagePickerPopover } from "@/components/core";
|
||||
// constants
|
||||
import { ETabIndices } from "@/constants/tab-indices";
|
||||
// helpers
|
||||
import { convertHexEmojiToDecimal } from "@/helpers/emoji.helper";
|
||||
import { getTabIndex } from "@/helpers/tab-indices.helper";
|
||||
|
||||
type Props = {
|
||||
handleClose: () => void;
|
||||
isMobile?: boolean;
|
||||
};
|
||||
const ProjectCreateHeader: React.FC<Props> = (props) => {
|
||||
const { handleClose } = props;
|
||||
const { handleClose, isMobile = false } = props;
|
||||
const { watch, control } = useFormContext<IProject>();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { getIndex } = getTabIndex(ETabIndices.PROJECT_CREATE, isMobile);
|
||||
|
||||
return (
|
||||
<div className="group relative h-44 w-full rounded-lg bg-custom-background-80">
|
||||
|
|
@ -26,7 +34,7 @@ const ProjectCreateHeader: React.FC<Props> = (props) => {
|
|||
)}
|
||||
|
||||
<div className="absolute right-2 top-2 p-2">
|
||||
<button data-posthog="PROJECT_MODAL_CLOSE" type="button" onClick={handleClose} tabIndex={8}>
|
||||
<button data-posthog="PROJECT_MODAL_CLOSE" type="button" onClick={handleClose} tabIndex={getIndex("close")}>
|
||||
<X className="h-5 w-5 text-white" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -35,7 +43,13 @@ const ProjectCreateHeader: React.FC<Props> = (props) => {
|
|||
name="cover_image"
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<ImagePickerPopover label="Change Cover" onChange={onChange} control={control} value={value} tabIndex={9} />
|
||||
<ImagePickerPopover
|
||||
label="Change Cover"
|
||||
onChange={onChange}
|
||||
control={control}
|
||||
value={value}
|
||||
tabIndex={getIndex("cover_image")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,22 +1,31 @@
|
|||
import { useFormContext } from "react-hook-form";
|
||||
import { IProject } from "@plane/types";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
// constants
|
||||
import { ETabIndices } from "@/constants/tab-indices";
|
||||
// helpers
|
||||
import { getTabIndex } from "@/helpers/tab-indices.helper";
|
||||
|
||||
type Props = {
|
||||
handleClose: () => void;
|
||||
isMobile?: boolean;
|
||||
};
|
||||
|
||||
const ProjectCreateButtons: React.FC<Props> = (props) => {
|
||||
const { handleClose } = props;
|
||||
const { handleClose, isMobile = false } = props;
|
||||
const {
|
||||
formState: { isSubmitting },
|
||||
} = useFormContext<IProject>();
|
||||
|
||||
const { getIndex } = getTabIndex(ETabIndices.PROJECT_CREATE, isMobile);
|
||||
|
||||
return (
|
||||
<div className="flex justify-end gap-2 py-4 border-t border-custom-border-100">
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose} tabIndex={6}>
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose} tabIndex={getIndex("cancel")}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="primary" type="submit" size="sm" loading={isSubmitting} tabIndex={7}>
|
||||
<Button variant="primary" type="submit" size="sm" loading={isSubmitting} tabIndex={getIndex("submit")}>
|
||||
{isSubmitting ? "Creating" : "Create project"}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { TProjectDisplayFilters, TProjectFilters } from "@plane/types";
|
|||
// components
|
||||
import { FilterOption } from "@/components/issues";
|
||||
import { FilterAccess, FilterCreatedDate, FilterLead, FilterMembers } from "@/components/project";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// types
|
||||
|
||||
type Props = {
|
||||
|
|
@ -19,6 +20,8 @@ export const ProjectFiltersSelection: React.FC<Props> = observer((props) => {
|
|||
const { displayFilters, filters, handleFiltersUpdate, handleDisplayFiltersUpdate, memberIds } = props;
|
||||
// states
|
||||
const [filtersSearchQuery, setFiltersSearchQuery] = useState("");
|
||||
// store
|
||||
const { isMobile } = usePlatformOS();
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col overflow-hidden">
|
||||
|
|
@ -31,7 +34,7 @@ export const ProjectFiltersSelection: React.FC<Props> = observer((props) => {
|
|||
placeholder="Search"
|
||||
value={filtersSearchQuery}
|
||||
onChange={(e) => setFiltersSearchQuery(e.target.value)}
|
||||
autoFocus
|
||||
autoFocus={!isMobile}
|
||||
/>
|
||||
{filtersSearchQuery !== "" && (
|
||||
<button type="button" className="grid place-items-center" onClick={() => setFiltersSearchQuery("")}>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue