Skip to content

Commit

Permalink
feat: move display options to icon button in header (#1138)
Browse files Browse the repository at this point in the history
  • Loading branch information
amanharwara committed Jun 22, 2022
1 parent d899e73 commit b0911b1
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const ContentList: FunctionComponent<Props> = ({

return (
<div
className="infinite-scroll focus:shadow-none focus:outline-none"
className="infinite-scroll border-solid border-0 border-t-1px border-main focus:shadow-none focus:outline-none"
id={ElementIds.ContentList}
onScroll={onScroll}
onKeyDown={onKeyDown}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ import ContentList from '@/Components/ContentListView/ContentList'
import NoAccountWarning from '@/Components/NoAccountWarning/NoAccountWarning'
import SearchOptions from '@/Components/SearchOptions/SearchOptions'
import PanelResizer, { PanelSide, ResizeFinishCallback, PanelResizeType } from '@/Components/PanelResizer/PanelResizer'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
import ContentListOptionsMenu from './ContentListOptionsMenu'
import Icon from '@/Components/Icon/Icon'
import { ItemListController } from '@/Controllers/ItemList/ItemListController'
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
Expand All @@ -31,6 +27,7 @@ import { NoAccountWarningController } from '@/Controllers/NoAccountWarningContro
import { NotesController } from '@/Controllers/NotesController'
import { AccountMenuController } from '@/Controllers/AccountMenu/AccountMenuController'
import { ElementIds } from '@/Constants/ElementIDs'
import ContentListHeader from './Header/ContentListHeader'

type Props = {
accountMenuController: AccountMenuController
Expand Down Expand Up @@ -58,32 +55,28 @@ const ContentListView: FunctionComponent<Props> = ({
selectionController,
}) => {
const itemsViewPanelRef = useRef<HTMLDivElement>(null)
const displayOptionsMenuRef = useRef<HTMLDivElement>(null)

const {
clearFilterText,
completedFullSync,
createNewNote,
noteFilterText,
onFilterEnter,
optionsSubtitle,
paginate,
panelTitle,
panelWidth,
renderedItems,
setNoteFilterText,
searchBarElement,
selectNextItem,
selectPreviousItem,
onFilterEnter,
clearFilterText,
paginate,
panelWidth,
createNewNote,
setNoteFilterText,
} = itemListController

const { selectedItems } = selectionController

const [showDisplayOptionsMenu, setShowDisplayOptionsMenu] = useState(false)
const [focusedSearch, setFocusedSearch] = useState(false)

const [closeDisplayOptMenuOnBlur] = useCloseOnBlur(displayOptionsMenuRef, setShowDisplayOptionsMenu)

const isFilesSmartView = useMemo(
() => navigationController.selected?.uuid === SystemViewId.Files,
[navigationController.selected?.uuid],
Expand Down Expand Up @@ -205,10 +198,6 @@ const ContentListView: FunctionComponent<Props> = ({
noteTagsController.reloadTagsContainerMaxWidth()
}, [noteTagsController])

const toggleDisplayOptionsMenu = useCallback(() => {
setShowDisplayOptionsMenu(!showDisplayOptionsMenu)
}, [showDisplayOptionsMenu])

const addButtonLabel = useMemo(
() => (isFilesSmartView ? 'Upload file' : 'Create a new note in the selected tag'),
[isFilesSmartView],
Expand All @@ -224,17 +213,14 @@ const ContentListView: FunctionComponent<Props> = ({
<div className="content">
<div id="items-title-bar" className="section-title-bar">
<div id="items-title-bar-container">
<div className="section-title-bar-header">
<div className="sk-h2 font-semibold title">{panelTitle}</div>
<button
className="flex items-center px-5 py-1 bg-contrast hover:brightness-130 color-text border-0 cursor-pointer"
title={addButtonLabel}
aria-label={addButtonLabel}
onClick={addNewItem}
>
<Icon type="add" className="w-3.5 h-3.5" />
</button>
</div>
<ContentListHeader
application={application}
panelTitle={panelTitle}
addButtonLabel={addButtonLabel}
addNewItem={addNewItem}
isFilesSmartView={isFilesSmartView}
optionsSubtitle={optionsSubtitle}
/>
<div className="filter-section" role="search">
<div>
<input
Expand Down Expand Up @@ -268,38 +254,6 @@ const ContentListView: FunctionComponent<Props> = ({
noAccountWarningController={noAccountWarningController}
/>
</div>
<div id="items-menu-bar" className="sn-component" ref={displayOptionsMenuRef}>
<div className="sk-app-bar no-edges">
<div className="left">
<Disclosure open={showDisplayOptionsMenu} onChange={toggleDisplayOptionsMenu}>
<DisclosureButton
className={`sk-app-bar-item bg-contrast color-text 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 && (
<ContentListOptionsMenu
application={application}
closeDisplayOptionsMenu={toggleDisplayOptionsMenu}
closeOnBlur={closeDisplayOptMenuOnBlur}
isOpen={showDisplayOptionsMenu}
navigationController={navigationController}
/>
)}
</DisclosurePanel>
</Disclosure>
</div>
</div>
</div>
</div>
{completedFullSync && !renderedItems.length ? <p className="empty-items-list faded">No items.</p> : null}
{!completedFullSync && !renderedItems.length ? <p className="empty-items-list faded">Loading...</p> : null}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { WebApplication } from '@/Application/Application'
import { Disclosure, DisclosurePanel } from '@reach/disclosure'
import { memo, useCallback, useRef, useState } from 'react'
import Icon from '../../Icon/Icon'
import { DisplayOptionsMenuPositionProps } from './DisplayOptionsMenuProps'
import DisplayOptionsMenuPortal from './DisplayOptionsMenuPortal'
import StyledDisplayOptionsButton from './StyledDisplayOptionsButton'

type Props = {
application: {
getPreference: WebApplication['getPreference']
setPreference: WebApplication['setPreference']
}
panelTitle: string
addButtonLabel: string
addNewItem: () => void
isFilesSmartView: boolean
optionsSubtitle?: string
}

const ContentListHeader = ({
application,
panelTitle,
addButtonLabel,
addNewItem,
isFilesSmartView,
optionsSubtitle,
}: Props) => {
const [displayOptionsMenuPosition, setDisplayOptionsMenuPosition] = useState<DisplayOptionsMenuPositionProps>()
const displayOptionsContainerRef = useRef<HTMLDivElement>(null)
const displayOptionsButtonRef = useRef<HTMLButtonElement>(null)

const [showDisplayOptionsMenu, setShowDisplayOptionsMenu] = useState(false)

const toggleDisplayOptionsMenu = useCallback(() => {
if (displayOptionsButtonRef.current) {
const buttonBoundingRect = displayOptionsButtonRef.current.getBoundingClientRect()
setDisplayOptionsMenuPosition({
top: buttonBoundingRect.bottom,
left: buttonBoundingRect.right - buttonBoundingRect.width,
})
}

setShowDisplayOptionsMenu((show) => !show)
}, [])

return (
<div className="section-title-bar-header">
<div className="flex flex-col">
<div className="text-lg font-semibold title">{panelTitle}</div>
{optionsSubtitle && <div className="text-xs color-passive-0">{optionsSubtitle}</div>}
</div>
<div className="flex">
<div className="relative" ref={displayOptionsContainerRef}>
<Disclosure open={showDisplayOptionsMenu} onChange={toggleDisplayOptionsMenu}>
<StyledDisplayOptionsButton pressed={showDisplayOptionsMenu} ref={displayOptionsButtonRef}>
<Icon type="sort-descending" className="w-5 h-5" />
</StyledDisplayOptionsButton>
<DisclosurePanel>
{showDisplayOptionsMenu && displayOptionsMenuPosition && (
<DisplayOptionsMenuPortal
application={application}
closeDisplayOptionsMenu={toggleDisplayOptionsMenu}
containerRef={displayOptionsContainerRef}
isOpen={showDisplayOptionsMenu}
isFilesSmartView={isFilesSmartView}
top={displayOptionsMenuPosition.top}
left={displayOptionsMenuPosition.left}
/>
)}
</DisclosurePanel>
</Disclosure>
</div>
<button
className="flex justify-center items-center min-w-8 h-8 ml-3 bg-info hover:brightness-130 color-info-contrast border-1 border-solid border-transparent rounded-full cursor-pointer"
title={addButtonLabel}
aria-label={addButtonLabel}
onClick={addNewItem}
>
<Icon type="add" className="w-5 h-5" />
</button>
</div>
</div>
)
}

export default memo(ContentListHeader)
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
import { WebApplication } from '@/Application/Application'
import { CollectionSort, CollectionSortProperty, PrefKey, SystemViewId } from '@standardnotes/snjs'
import { CollectionSort, CollectionSortProperty, PrefKey } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useState } from 'react'
import Icon from '@/Components/Icon/Icon'
import Menu from '@/Components/Menu/Menu'
import MenuItem from '@/Components/Menu/MenuItem'
import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator'
import { MenuItemType } from '@/Components/Menu/MenuItemType'
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
import { DisplayOptionsMenuProps } from './DisplayOptionsMenuProps'

type Props = {
application: WebApplication
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void
closeDisplayOptionsMenu: () => void
isOpen: boolean
navigationController: NavigationController
}

const ContentListOptionsMenu: FunctionComponent<Props> = ({
const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
closeDisplayOptionsMenu,
closeOnBlur,
application,
isOpen,
navigationController,
isFilesSmartView,
}) => {
const [sortBy, setSortBy] = useState(() => application.getPreference(PrefKey.SortNotesBy, CollectionSort.CreatedAt))
const [sortReverse, setSortReverse] = useState(() => application.getPreference(PrefKey.SortNotesReverse, false))
Expand Down Expand Up @@ -109,9 +99,9 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
return (
<Menu
className={
'sn-dropdown sn-dropdown--animated min-w-70 overflow-y-auto \
'py-1 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 top-full left-2 absolute'
flex flex-col'
}
a11yLabel="Notes list options menu"
closeMenu={closeDisplayOptionsMenu}
Expand All @@ -123,7 +113,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
type={MenuItemType.RadioButton}
onClick={toggleSortByDateModified}
checked={sortBy === CollectionSort.UpdatedAt}
onBlur={closeOnBlur}
>
<div className="flex flex-grow items-center justify-between ml-2">
<span>Date modified</span>
Expand All @@ -141,7 +130,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
type={MenuItemType.RadioButton}
onClick={toggleSortByCreationDate}
checked={sortBy === CollectionSort.CreatedAt}
onBlur={closeOnBlur}
>
<div className="flex flex-grow items-center justify-between ml-2">
<span>Creation date</span>
Expand All @@ -159,7 +147,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
type={MenuItemType.RadioButton}
onClick={toggleSortByTitle}
checked={sortBy === CollectionSort.Title}
onBlur={closeOnBlur}
>
<div className="flex flex-grow items-center justify-between ml-2">
<span>Title</span>
Expand All @@ -174,13 +161,12 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
</MenuItem>
<MenuItemSeparator />
<div className="px-3 py-1 text-xs font-semibold color-text uppercase">View</div>
{navigationController.selectedUuid !== SystemViewId.Files && (
{!isFilesSmartView && (
<MenuItem
type={MenuItemType.SwitchButton}
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 @@ -190,7 +176,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hideDate}
onChange={toggleHideDate}
onBlur={closeOnBlur}
>
Show date
</MenuItem>
Expand All @@ -199,7 +184,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hideTags}
onChange={toggleHideTags}
onBlur={closeOnBlur}
>
Show tags
</MenuItem>
Expand All @@ -208,7 +192,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hideEditorIcon}
onChange={toggleEditorIcon}
onBlur={closeOnBlur}
>
Show icon
</MenuItem>
Expand All @@ -219,7 +202,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hidePinned}
onChange={toggleHidePinned}
onBlur={closeOnBlur}
>
Show pinned
</MenuItem>
Expand All @@ -228,7 +210,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!hideProtected}
onChange={toggleHideProtected}
onBlur={closeOnBlur}
>
Show protected
</MenuItem>
Expand All @@ -237,7 +218,6 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={showArchived}
onChange={toggleShowArchived}
onBlur={closeOnBlur}
>
Show archived
</MenuItem>
Expand All @@ -246,12 +226,11 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={showTrashed}
onChange={toggleShowTrashed}
onBlur={closeOnBlur}
>
Show trashed
</MenuItem>
</Menu>
)
}

export default observer(ContentListOptionsMenu)
export default observer(DisplayOptionsMenu)
Loading

0 comments on commit b0911b1

Please sign in to comment.