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: notes list options menu not toggling correctly #840

Merged
merged 5 commits into from
Feb 1, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
21 changes: 14 additions & 7 deletions app/assets/javascripts/components/NotesListOptionsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import { useRef, useState } from 'preact/hooks';
import { Icon } from './Icon';
import { Menu } from './menu/Menu';
import { MenuItem, MenuItemSeparator, MenuItemType } from './menu/MenuItem';
import { useCloseOnClickOutside } from './utils';

type Props = {
application: WebApplication;
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void;
closeDisplayOptionsMenu: () => void;
};

export const NotesListOptionsMenu: FunctionComponent<Props> = observer(
({ closeDisplayOptionsMenu, application }) => {
({ closeDisplayOptionsMenu, closeOnBlur, application }) => {
const menuClassName =
'sn-dropdown sn-dropdown--animated min-w-70 overflow-y-auto \
border-1 border-solid border-main text-sm z-index-dropdown-menu \
flex flex-col py-2 bottom-0 left-2 absolute';
flex flex-col py-2 top-full bottom-0 left-2 absolute';
const [sortBy, setSortBy] = useState(() =>
application.getPreference(PrefKey.SortNotesBy, CollectionSort.CreatedAt)
);
Expand Down Expand Up @@ -118,10 +118,6 @@ flex flex-col py-2 bottom-0 left-2 absolute';

const menuRef = useRef<HTMLDivElement>(null);

useCloseOnClickOutside(menuRef, () => {
closeDisplayOptionsMenu();
});

return (
<div ref={menuRef} className={menuClassName}>
<Menu a11yLabel="Sort by" closeMenu={closeDisplayOptionsMenu}>
Expand All @@ -133,6 +129,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
type={MenuItemType.RadioButton}
onClick={toggleSortByDateModified}
checked={sortBy === CollectionSort.UpdatedAt}
onBlur={closeOnBlur}
>
<div className="flex flex-grow items-center justify-between">
<span>Date modified</span>
Expand All @@ -150,6 +147,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
type={MenuItemType.RadioButton}
onClick={toggleSortByCreationDate}
checked={sortBy === CollectionSort.CreatedAt}
onBlur={closeOnBlur}
>
<div className="flex flex-grow items-center justify-between">
<span>Creation date</span>
Expand All @@ -167,6 +165,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
type={MenuItemType.RadioButton}
onClick={toggleSortByTitle}
checked={sortBy === CollectionSort.Title}
onBlur={closeOnBlur}
>
<div className="flex flex-grow items-center justify-between">
<span>Title</span>
Expand All @@ -188,6 +187,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hidePreview}
onChange={toggleHidePreview}
onBlur={closeOnBlur}
>
<div className="flex flex-col max-w-3/4">Show note preview</div>
</MenuItem>
Expand All @@ -196,6 +196,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hideDate}
onChange={toggleHideDate}
onBlur={closeOnBlur}
>
Show date
</MenuItem>
Expand All @@ -204,6 +205,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hideTags}
onChange={toggleHideTags}
onBlur={closeOnBlur}
>
Show tags
</MenuItem>
Expand All @@ -212,6 +214,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hideEditorIcon}
onChange={toggleEditorIcon}
onBlur={closeOnBlur}
>
Show editor icon
</MenuItem>
Expand All @@ -224,6 +227,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hidePinned}
onChange={toggleHidePinned}
onBlur={closeOnBlur}
>
Show pinned notes
</MenuItem>
Expand All @@ -232,6 +236,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hideProtected}
onChange={toggleHideProtected}
onBlur={closeOnBlur}
>
Show protected notes
</MenuItem>
Expand All @@ -240,6 +245,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={showArchived}
onChange={toggleShowArchived}
onBlur={closeOnBlur}
>
Show archived notes
</MenuItem>
Expand All @@ -248,6 +254,7 @@ flex flex-col py-2 bottom-0 left-2 absolute';
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={showTrashed}
onChange={toggleShowTrashed}
onBlur={closeOnBlur}
>
Show trashed notes
</MenuItem>
Expand Down
78 changes: 52 additions & 26 deletions app/assets/javascripts/components/NotesView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { PANEL_NAME_NOTES } from '@/views/constants';
import { PrefKey } from '@standardnotes/snjs';
import { observer } from 'mobx-react-lite';
import { FunctionComponent } from 'preact';
import { useEffect, useRef } from 'preact/hooks';
import { useEffect, useRef, useState } from 'preact/hooks';
import { NoAccountWarning } from './NoAccountWarning';
import { NotesList } from './NotesList';
import { NotesListOptionsMenu } from './NotesListOptionsMenu';
Expand All @@ -16,6 +16,12 @@ import {
PanelResizer,
PanelResizeType,
} from './PanelResizer';
import {
Disclosure,
DisclosureButton,
DisclosurePanel,
} from '@reach/disclosure';
import { useCloseOnBlur } from './utils';

type Props = {
application: WebApplication;
Expand All @@ -25,6 +31,7 @@ type Props = {
export const NotesView: FunctionComponent<Props> = observer(
({ application, appState }) => {
const notesViewPanelRef = useRef<HTMLDivElement>(null);
const displayOptionsMenuRef = useRef<HTMLDivElement>(null);

const {
completedFullSync,
Expand All @@ -36,8 +43,8 @@ export const NotesView: FunctionComponent<Props> = observer(
renderedNotes,
selectedNotes,
setNoteFilterText,
showDisplayOptionsMenu,
toggleDisplayOptionsMenu,
/* showDisplayOptionsMenu,
setShowDisplayOptionsMenu, */
searchBarElement,
selectNextNote,
selectPreviousNote,
Expand All @@ -49,6 +56,13 @@ export const NotesView: FunctionComponent<Props> = observer(
panelWidth,
} = appState.notesView;

const [showDisplayOptionsMenu, setShowDisplayOptionsMenu] = useState(false);

const [closeDisplayOptMenuOnBlur] = useCloseOnBlur(
displayOptionsMenuRef,
setShowDisplayOptionsMenu
);

useEffect(() => {
handleFilterTextChanged();
}, [noteFilterText, handleFilterTextChanged]);
Expand Down Expand Up @@ -139,6 +153,10 @@ export const NotesView: FunctionComponent<Props> = observer(
appState.noteTags.reloadTagsContainerMaxWidth();
};

const toggleDisplayOptionsMenu = () => {
setShowDisplayOptionsMenu(!showDisplayOptionsMenu);
};

return (
<div
id="notes-column"
Expand Down Expand Up @@ -192,34 +210,42 @@ export const NotesView: FunctionComponent<Props> = observer(
</div>
<NoAccountWarning appState={appState} />
</div>
<div id="notes-menu-bar" className="sn-component">
<div
id="notes-menu-bar"
className="sn-component"
ref={displayOptionsMenuRef}
>
<div className="sk-app-bar no-edges">
<div className="left">
<div
className={`sk-app-bar-item ${
showDisplayOptionsMenu ? 'selected' : ''
}`}
onClick={() =>
toggleDisplayOptionsMenu(!showDisplayOptionsMenu)
}
<Disclosure
open={showDisplayOptionsMenu}
onChange={toggleDisplayOptionsMenu}
>
<div className="sk-app-bar-item-column">
<div className="sk-label">Options</div>
</div>
<div className="sk-app-bar-item-column">
<div className="sk-sublabel">{optionsSubtitle}</div>
</div>
</div>
<DisclosureButton
className={`sk-app-bar-item bg-contrast border-0 focus:shadow-none ${
showDisplayOptionsMenu ? 'selected' : ''
}`}
onBlur={closeDisplayOptMenuOnBlur}
>
<div className="sk-app-bar-item-column">
<div className="sk-label">Options</div>
</div>
<div className="sk-app-bar-item-column">
<div className="sk-sublabel">{optionsSubtitle}</div>
</div>
</DisclosureButton>
<DisclosurePanel onBlur={closeDisplayOptMenuOnBlur}>
{showDisplayOptionsMenu && (
<NotesListOptionsMenu
application={application}
closeDisplayOptionsMenu={toggleDisplayOptionsMenu}
closeOnBlur={closeDisplayOptMenuOnBlur}
/>
)}
</DisclosurePanel>
</Disclosure>
</div>
</div>
{showDisplayOptionsMenu && (
<NotesListOptionsMenu
application={application}
closeDisplayOptionsMenu={() =>
toggleDisplayOptionsMenu(false)
}
/>
)}
</div>
</div>
{completedFullSync && !renderedNotes.length ? (
Expand Down
35 changes: 21 additions & 14 deletions app/assets/javascripts/components/menu/MenuItem.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import {
ComponentChild,
ComponentChildren,
FunctionComponent,
VNode,
} from 'preact';
import { ComponentChildren, FunctionComponent, VNode } from 'preact';
import { forwardRef, Ref } from 'preact/compat';
import { JSXInternal } from 'preact/src/jsx';
import { Icon } from '../Icon';
import { Switch, SwitchProps } from '../Switch';
import { IconType } from '@standardnotes/snjs';
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/views/constants';

export enum MenuItemType {
IconButton,
Expand All @@ -21,6 +17,7 @@ type MenuItemProps = {
children: ComponentChildren;
onClick?: JSXInternal.MouseEventHandler<HTMLButtonElement>;
onChange?: SwitchProps['onChange'];
onBlur?: (event: { relatedTarget: EventTarget | null }) => void;
className?: string;
checked?: boolean;
icon?: IconType;
Expand All @@ -34,6 +31,7 @@ export const MenuItem: FunctionComponent<MenuItemProps> = forwardRef(
children,
onClick,
onChange,
onBlur,
className = '',
type,
checked,
Expand All @@ -45,22 +43,31 @@ export const MenuItem: FunctionComponent<MenuItemProps> = forwardRef(
) => {
return type === MenuItemType.SwitchButton &&
typeof onChange === 'function' ? (
<Switch
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={checked}
onChange={onChange}
<button
className="sn-dropdown-item focus:bg-info-backdrop focus:shadow-none justify-between"
onClick={() => {
onChange(!checked);
}}
onBlur={onBlur}
tabIndex={
typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE
}
role="menuitemcheckbox"
tabIndex={typeof tabIndex === 'number' ? tabIndex : -1}
aria-checked={checked}
>
{children}
</Switch>
<span className="flex flex-grow items-center">{children}</span>
<Switch className="px-0" checked={checked} />
</button>
) : (
<button
ref={ref}
role={type === MenuItemType.RadioButton ? 'menuitemradio' : 'menuitem'}
tabIndex={typeof tabIndex === 'number' ? tabIndex : -1}
tabIndex={
typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE
}
className={`sn-dropdown-item focus:bg-info-backdrop focus:shadow-none ${className}`}
onClick={onClick}
onBlur={onBlur}
{...(type === MenuItemType.RadioButton
? { 'aria-checked': checked }
: {})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export class NotesViewState {
} else if (eventName === AppStateEvent.ActiveEditorChanged) {
this.handleEditorChange();
} else if (eventName === AppStateEvent.EditorFocused) {
this.toggleDisplayOptionsMenu(false);
this.setShowDisplayOptionsMenu(false);
}
})
);
Expand All @@ -169,7 +169,7 @@ export class NotesViewState {
setCompletedFullSync: action,
setNoteFilterText: action,
syncSelectedNotes: action,
toggleDisplayOptionsMenu: action,
setShowDisplayOptionsMenu: action,
onFilterEnter: action,
handleFilterTextChanged: action,

Expand All @@ -185,7 +185,7 @@ export class NotesViewState {
this.completedFullSync = completed;
};

toggleDisplayOptionsMenu = (enabled: boolean) => {
setShowDisplayOptionsMenu = (enabled: boolean) => {
this.showDisplayOptionsMenu = enabled;
};

Expand Down Expand Up @@ -505,7 +505,7 @@ export class NotesViewState {

handleTagChange = () => {
this.resetScrollPosition();
this.toggleDisplayOptionsMenu(false);
this.setShowDisplayOptionsMenu(false);
this.setNoteFilterText('');
this.application.getDesktopService().searchText();
this.resetPagination();
Expand Down
4 changes: 4 additions & 0 deletions app/assets/stylesheets/_sn.scss
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,10 @@
top: 50%;
}

.top-full {
top: 100%;
}

.left-2 {
left: 0.5rem;
}
Expand Down