Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: file popover not closing when click inside editor #924

Merged
merged 5 commits into from
Mar 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { observer } from 'mobx-react-lite';
import { FunctionComponent } from 'preact';
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import { Icon } from '../Icon';
import { useCloseOnClickOutside } from '../utils';
import { useCloseOnBlur } from '../utils';
import {
ChallengeReason,
ContentType,
Expand Down Expand Up @@ -66,9 +66,7 @@ export const AttachedFilesButton: FunctionComponent<Props> = observer(
const buttonRef = useRef<HTMLButtonElement>(null);
const panelRef = useRef<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
useCloseOnClickOutside(containerRef, () => {
setOpen(false);
});
const [closeOnBlur, keepMenuOpen] = useCloseOnBlur(containerRef, setOpen);

const [attachedFilesCount, setAttachedFilesCount] = useState(
note ? application.items.getFilesForNote(note).length : 0
Expand Down Expand Up @@ -170,7 +168,10 @@ export const AttachedFilesButton: FunctionComponent<Props> = observer(
const toggleFileProtection = async (file: SNFile) => {
let result: SNFile | undefined;
if (file.protected) {
keepMenuOpen(true);
result = await application.protections.unprotectFile(file);
keepMenuOpen(false);
buttonRef.current?.focus();
} else {
result = await application.protections.protectFile(file);
}
Expand Down Expand Up @@ -207,10 +208,13 @@ export const AttachedFilesButton: FunctionComponent<Props> = observer(
file.protected &&
action.type !== PopoverFileItemActionType.ToggleFileProtection
) {
keepMenuOpen(true);
isAuthorizedForAction = await authorizeProtectedActionForFile(
file,
ChallengeReason.AccessProtectedFile
);
keepMenuOpen(false);
buttonRef.current?.focus();
}

if (!isAuthorizedForAction) {
Expand Down Expand Up @@ -354,6 +358,7 @@ export const AttachedFilesButton: FunctionComponent<Props> = observer(
className={`sn-icon-button border-contrast ${
attachedFilesCount > 0 ? 'py-1 px-3' : ''
}`}
onBlur={closeOnBlur}
>
<VisuallyHidden>Attached files</VisuallyHidden>
<Icon type="attachment-file" className="block" />
Expand All @@ -374,6 +379,7 @@ export const AttachedFilesButton: FunctionComponent<Props> = observer(
maxHeight,
}}
className="sn-dropdown sn-dropdown--animated min-w-80 max-h-120 max-w-xs flex flex-col overflow-y-auto fixed"
onBlur={closeOnBlur}
>
{open && (
<AttachedFilesPopover
Expand All @@ -382,6 +388,7 @@ export const AttachedFilesButton: FunctionComponent<Props> = observer(
note={note}
handleFileAction={handleFileAction}
currentTab={currentTab}
closeOnBlur={closeOnBlur}
setCurrentTab={setCurrentTab}
isDraggingFiles={isDraggingFiles}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/constants';
import { WebApplication } from '@/ui_models/application';
import { AppState } from '@/ui_models/app_state';
import { ContentType, SNFile, SNNote } from '@standardnotes/snjs';
Expand All @@ -22,6 +23,7 @@ type Props = {
application: WebApplication;
appState: AppState;
currentTab: PopoverTabs;
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void;
handleFileAction: (action: PopoverFileItemAction) => Promise<boolean>;
isDraggingFiles: boolean;
note: SNNote;
Expand All @@ -33,6 +35,7 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
application,
appState,
currentTab,
closeOnBlur,
handleFileAction,
isDraggingFiles,
note,
Expand Down Expand Up @@ -100,6 +103,7 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
return (
<div
className="flex flex-col"
tabIndex={FOCUSABLE_BUT_NOT_TABBABLE}
style={{
border: isDraggingFiles
? '2px dashed var(--sn-stylekit-info-color)'
Expand All @@ -116,6 +120,7 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
onClick={() => {
setCurrentTab(PopoverTabs.AttachedFiles);
}}
onBlur={closeOnBlur}
>
Attached
</button>
Expand All @@ -128,6 +133,7 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
onClick={() => {
setCurrentTab(PopoverTabs.AllFiles);
}}
onBlur={closeOnBlur}
>
All files
</button>
Expand All @@ -144,13 +150,15 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
onInput={(e) => {
setSearchQuery((e.target as HTMLInputElement).value);
}}
onBlur={closeOnBlur}
/>
{searchQuery.length > 0 && (
<button
className="flex absolute right-2 p-0 bg-transparent border-0 top-1/2 -translate-y-1/2 cursor-pointer"
onClick={() => {
setSearchQuery('');
}}
onBlur={closeOnBlur}
>
<Icon
type="clear-circle-filled"
Expand All @@ -170,6 +178,7 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
isAttachedToNote={attachedFiles.includes(file)}
handleFileAction={handleFileAction}
getIconType={application.iconsController.getIconForFileType}
closeOnBlur={closeOnBlur}
/>
);
})
Expand All @@ -190,7 +199,11 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
? 'No files attached to this note'
: 'No files found in this account'}
</div>
<Button type="normal" onClick={handleAttachFilesClick}>
<Button
type="normal"
onClick={handleAttachFilesClick}
onBlur={closeOnBlur}
>
{currentTab === PopoverTabs.AttachedFiles ? 'Attach' : 'Upload'}{' '}
files
</Button>
Expand All @@ -204,6 +217,7 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
<button
className="sn-dropdown-item py-3 border-0 border-t-1px border-solid border-main focus:bg-info-backdrop"
onClick={handleAttachFilesClick}
onBlur={closeOnBlur}
>
<Icon type="add" className="mr-2 color-neutral" />
{currentTab === PopoverTabs.AttachedFiles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ export type PopoverFileItemProps = {
isAttachedToNote: boolean;
handleFileAction: (action: PopoverFileItemAction) => Promise<boolean>;
getIconType(type: string): IconType;
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void;
};

export const PopoverFileItem: FunctionComponent<PopoverFileItemProps> = ({
file,
isAttachedToNote,
handleFileAction,
getIconType,
closeOnBlur,
}) => {
const [fileName, setFileName] = useState(file.name);
const [isRenamingFile, setIsRenamingFile] = useState(false);
Expand Down Expand Up @@ -93,6 +95,7 @@ export const PopoverFileItem: FunctionComponent<PopoverFileItemProps> = ({
isAttachedToNote={isAttachedToNote}
handleFileAction={handleFileAction}
setIsRenamingFile={setIsRenamingFile}
closeOnBlur={closeOnBlur}
/>
</div>
);
Expand Down
3 changes: 3 additions & 0 deletions app/assets/javascripts/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type ButtonProps = {
| TargetedEvent<HTMLFormElement>
| TargetedMouseEvent<HTMLButtonElement>
) => void;
onBlur?: (event: FocusEvent) => void;
disabled?: boolean;
};

Expand All @@ -34,6 +35,7 @@ export const Button: FunctionComponent<ButtonProps> = forwardRef(
type,
label,
className = '',
onBlur,
onClick,
disabled = false,
children,
Expand All @@ -46,6 +48,7 @@ export const Button: FunctionComponent<ButtonProps> = forwardRef(
return (
<button
className={`${buttonClass} ${cursorClass} ${className}`}
onBlur={onBlur}
onClick={(e) => {
onClick(e);
e.preventDefault();
Expand Down