Skip to content

Commit

Permalink
shared: several small UI improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
flsilva committed Aug 14, 2023
1 parent 581070f commit bb90dd7
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 14 deletions.
16 changes: 12 additions & 4 deletions src/app/app/shared/project/ProjectModal.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
'use client';

import { useEffect, useRef, useState } from 'react';
import { Dialog } from '@headlessui/react';
import { XIcon } from '@/app/shared/ui/icon/XIcon';
import {
buttonClassNameGreen,
buttonClassNameWhite,
} from '@/app/shared/ui//button/buttonClassName';
import { ProjectData } from './ProjectData';
import { useEffect, useState } from 'react';
import { CreateProjectData, UpdateProjectData } from './ProjectData';

interface ProjectModalProps {
Expand All @@ -32,6 +32,7 @@ export default function ProjectModal({
*/
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const inputNameRef = useRef(null);

useEffect(() => {
setNameAccordingToProject(project);
Expand Down Expand Up @@ -99,17 +100,23 @@ export default function ProjectModal({
};

return (
<Dialog as="div" open={open} className="relative z-50" onClose={onCloseHandlerInternal}>
<Dialog
as="div"
open={open}
className="relative z-50"
initialFocus={inputNameRef}
onClose={onCloseHandlerInternal}
>
<div className="fixed inset-0 bg-black/30" aria-hidden="true" />
<div className="fixed inset-0 flex items-center">
<div className="fixed inset-0 flex md:items-center">
<Dialog.Panel className="mx-auto w-full rounded-lg bg-white p-4 md:w-[40rem]">
<div className="flex items-center justify-between">
<h1 className="text-lg font-semibold text-gray-800">
{project !== undefined && project !== null ? 'Edit project' : 'Create project'}
</h1>
<button
type="button"
className="-m-2.5 rounded-md p-2.5 text-gray-700"
className="-m-2.5 rounded-md p-1.5 text-gray-700 hover:bg-gray-200"
onClick={onCloseHandlerInternal}
>
<span className="sr-only">Close modal</span>
Expand All @@ -126,6 +133,7 @@ export default function ProjectModal({
className="mb-6 block w-full rounded-md border border-gray-400 py-1.5 text-gray-900 ring-0 placeholder:text-gray-400 focus:border-gray-900 focus:outline-0 focus:ring-0"
required
autoComplete="off"
ref={inputNameRef}
/>
<textarea
value={description}
Expand Down
4 changes: 2 additions & 2 deletions src/app/app/shared/task/TaskDueDatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export default function TaskDueDatePicker({ defaultDate, onChange }: TaskDueDate
<div className="flex flex-row">
<button
type="button"
className="flex rounded-md p-2 hover:bg-gray-300"
className="flex rounded-md p-1.5 hover:bg-gray-200"
onClick={() => setIsShowing(!isShowing)}
>
<span className="sr-only">Add due date</span>
Expand All @@ -86,7 +86,7 @@ export default function TaskDueDatePicker({ defaultDate, onChange }: TaskDueDate
{selectedDate && (
<button
type="button"
className="flex rounded-md py-2 hover:bg-gray-300 sm:px-2"
className="flex rounded-md p-1.5 hover:bg-gray-200"
onClick={() => handleChange(null)}
>
<span className="sr-only">Remove due date</span>
Expand Down
22 changes: 19 additions & 3 deletions src/app/app/shared/task/TaskForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import 'client-only';
import { useRouter } from 'next/navigation';
import { Fragment, useEffect, useState } from 'react';
import { Fragment, useState } from 'react';
import ContentEditable from 'react-contenteditable';
import { Menu } from '@headlessui/react';
import { ClassNamePropsOptional } from '@/app/shared/ui/ClassNameProps';
Expand All @@ -29,6 +29,7 @@ import {
updateTaskProject,
} from './task-model';
import TaskCheck, { TaskCheckSize } from './TaskCheck';
import { useAutoFocus } from '@/app/shared/useAutoFocus';

interface TaskFormProps extends ClassNamePropsOptional {
readonly defaultDueDate?: Date | null;
Expand Down Expand Up @@ -64,6 +65,7 @@ export default function TaskForm({
const [isEditingNameOrDescription, setIsEditingNameOrDescription] = useState(
shouldStartEditingNameOrDescription,
);
const inputNameRef = useAutoFocus();

const generateTaskData = (): CreateTaskData => ({
name: (name !== NAME_PLACEHOLDER && name) || '',
Expand Down Expand Up @@ -100,6 +102,9 @@ export default function TaskForm({
*/
router.refresh();
/**/
setTimeout(() => {
inputNameRef.current?.focus();
}, 300);
};

const onDueDateChange = async (date: Date | null) => {
Expand Down Expand Up @@ -140,17 +145,27 @@ export default function TaskForm({
* works to keep the focus on the <button> but doesn't prevent triggering this focus event.
*/
const relatedTarget = event.relatedTarget;
console.log('TaskForm().onNameFocusHandler() - relatedTarget: ', relatedTarget);
if (
relatedTarget !== undefined &&
relatedTarget !== null &&
relatedTarget.attributes.getNamedItem('data-headlessui-focus-guard') !== undefined &&
relatedTarget.attributes.getNamedItem('data-headlessui-focus-guard') !== null
)
) {
console.log('TaskForm().onNameFocusHandler() - RETURN');
return;
}
/**/
console.log('TaskForm().onNameFocusHandler() - CALL setIsEditingNameOrDescription()');
console.log('TaskForm().onNameFocusHandler() - event.target: ', event.target);
console.log(
'TaskForm().onNameFocusHandler() - event.target.innerHTML: ',
event.target.innerHTML,
);
setIsEditingNameOrDescription(true);
if (event.target === null || event.target === undefined) return;
if (event.target.innerHTML !== '' && event.target.innerHTML !== NAME_PLACEHOLDER) return;
console.log('TaskForm().onNameFocusHandler() - CALL setName()');
setName('');
};

Expand Down Expand Up @@ -241,6 +256,7 @@ export default function TaskForm({
<ContentEditable
className={nameClassName}
html={name}
innerRef={task ? undefined : inputNameRef}
onBlur={onNameBlurHandler}
onFocus={onNameFocusHandler}
onChange={onNameChangeHandler}
Expand All @@ -262,7 +278,7 @@ export default function TaskForm({
items={getItemsForProjectsDropdown()}
itemsClassName="absolute bottom-14 left-0 max-h-80 w-56"
menuButton={
<Menu.Button className="flex items-center justify-center rounded-md bg-green-600 px-3.5 py-2.5 text-sm font-medium text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600">
<Menu.Button className="flex items-center justify-center rounded-md bg-green-600 px-3.5 py-1.5 text-sm font-medium text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600">
{taskProject.name}
<ExpandMoreIcon className="ml-2 fill-white" />
</Menu.Button>
Expand Down
4 changes: 2 additions & 2 deletions src/app/app/shared/task/TaskModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export default function TaskModal({ project, projects, task }: TaskModalModalPro
<div className="flex">
<button
type="button"
className="-mt-1 rounded-md p-2.5 text-gray-700"
className="rounded-md p-1.5 text-gray-700 hover:bg-gray-200"
onClick={onDeleteTask}
ref={closeButtonRef}
>
Expand All @@ -118,7 +118,7 @@ export default function TaskModal({ project, projects, task }: TaskModalModalPro
</button>
<button
type="button"
className="-mt-1 rounded-md p-2.5 text-gray-700"
className="rounded-md ml-2 p-1.5 text-gray-700 hover:bg-gray-200"
onClick={onCloseModal}
ref={closeButtonRef}
>
Expand Down
4 changes: 2 additions & 2 deletions src/app/app/shared/ui/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ const AppHeader = forwardRef<HTMLElement, AppHeaderProps>(
<div className="relative">
<DropdownMenu
items={getDropdownItems()}
itemsClassName="absolute top-8 right-0 max-h-80 w-56"
itemsClassName="absolute top-8 right-0 max-h-80 w-56 z-10"
menuButton={
<Menu.Button className="flex items-center justify-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600">
<Menu.Button className="flex items-center justify-center outline-none">
<PersonIcon className="fill-white hover:fill-green-500" />
</Menu.Button>
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/auth/sign-in/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default function SignIn() {
);

return (
<div>
<div className="pb-24">
<h2 className="mb-9 mt-12 text-center text-xl font-semibold text-gray-900">Sign in</h2>
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
<OAuthProviderButton provider="google">
Expand Down
15 changes: 15 additions & 0 deletions src/app/shared/useAutoFocus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use client';

import 'client-only';
import { useEffect, useRef } from 'react';

export const useAutoFocus = () => {
const inputRef = useRef<HTMLElement>(null);

useEffect(() => {
if (!inputRef.current) return;
inputRef.current.focus();
}, []);

return inputRef;
};
3 changes: 3 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ module.exports = {
'./src/shared/**/*.{js,ts,jsx,tsx,mdx}',
"./node_modules/tailwind-datepicker-react/dist/**/*.js",
],
future: {
hoverOnlyWhenSupported: true,
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
Expand Down

0 comments on commit bb90dd7

Please sign in to comment.