Skip to content

Commit

Permalink
feat: New notes list design (#780)
Browse files Browse the repository at this point in the history
  • Loading branch information
amanharwara authored Jan 4, 2022
1 parent 954f399 commit 7dd4a60
Show file tree
Hide file tree
Showing 20 changed files with 296 additions and 155 deletions.
7 changes: 4 additions & 3 deletions app/assets/icons/ic-authenticator.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions app/assets/icons/ic-code.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions app/assets/icons/ic-lock-filled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions app/assets/icons/ic-markdown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/icons/ic-pin-filled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions app/assets/icons/ic-spreadsheets.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions app/assets/icons/ic-tasks.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions app/assets/icons/ic-text-paragraph.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions app/assets/icons/ic-text-rich.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions app/assets/icons/ic-trash-filled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 11 additions & 7 deletions app/assets/javascripts/components/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useState } from 'preact/hooks';

export type DropdownItem = {
icon?: IconType;
iconClassName?: string;
label: string;
value: string;
};
Expand All @@ -25,23 +26,21 @@ type DropdownProps = {
onChange: (value: string) => void;
};

type ListboxButtonProps = {
icon?: IconType;
value: string | null;
label: string;
type ListboxButtonProps = DropdownItem & {
isExpanded: boolean;
};

const CustomDropdownButton: FunctionComponent<ListboxButtonProps> = ({
label,
isExpanded,
icon,
iconClassName = '',
}) => (
<>
<div className="sn-dropdown-button-label">
{icon ? (
<div className="flex mr-2">
<Icon type={icon} className="sn-icon--small" />
<Icon type={icon} className={`sn-icon--small ${iconClassName}`} />
</div>
) : null}
<div className="dropdown-selected-label">{label}</div>
Expand Down Expand Up @@ -85,11 +84,13 @@ export const Dropdown: FunctionComponent<DropdownProps> = ({
children={({ value, label, isExpanded }) => {
const current = items.find((item) => item.value === value);
const icon = current ? current?.icon : null;
const iconClassName = current ? current?.iconClassName : null;
return CustomDropdownButton({
value,
value: value ? value : label.toLowerCase(),
label,
isExpanded,
...(icon ? { icon } : null),
...(iconClassName ? { iconClassName } : null),
});
}}
/>
Expand All @@ -104,7 +105,10 @@ export const Dropdown: FunctionComponent<DropdownProps> = ({
>
{item.icon ? (
<div className="flex mr-3">
<Icon type={item.icon} className="sn-icon--small" />
<Icon
type={item.icon}
className={`sn-icon--small ${item.iconClassName ?? ''}`}
/>
</div>
) : null}
<div className="text-input">{item.label}</div>
Expand Down
21 changes: 19 additions & 2 deletions app/assets/javascripts/components/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import PencilOffIcon from '../../icons/ic-pencil-off.svg';
import PlainTextIcon from '../../icons/ic-text-paragraph.svg';
import RichTextIcon from '../../icons/ic-text-rich.svg';
import TrashIcon from '../../icons/ic-trash.svg';
import TrashFilledIcon from '../../icons/ic-trash-filled.svg';
import PinIcon from '../../icons/ic-pin.svg';
import PinFilledIcon from '../../icons/ic-pin-filled.svg';
import UnpinIcon from '../../icons/ic-pin-off.svg';
import ArchiveIcon from '../../icons/ic-archive.svg';
import UnarchiveIcon from '../../icons/ic-unarchive.svg';
Expand Down Expand Up @@ -52,6 +54,7 @@ import ServerIcon from '../../icons/ic-server.svg';
import EyeIcon from '../../icons/ic-eye.svg';
import EyeOffIcon from '../../icons/ic-eye-off.svg';
import LockIcon from '../../icons/ic-lock.svg';
import LockFilledIcon from '../../icons/ic-lock-filled.svg';
import ArrowsSortUpIcon from '../../icons/ic-arrows-sort-up.svg';
import ArrowsSortDownIcon from '../../icons/ic-arrows-sort-down.svg';
import WindowIcon from '../../icons/ic-window.svg';
Expand All @@ -69,6 +72,7 @@ const ICONS = {
'arrows-sort-up': ArrowsSortUpIcon,
'arrows-sort-down': ArrowsSortDownIcon,
lock: LockIcon,
'lock-filled': LockFilledIcon,
eye: EyeIcon,
'eye-off': EyeOffIcon,
server: ServerIcon,
Expand All @@ -89,7 +93,9 @@ const ICONS = {
spreadsheets: SpreadsheetsIcon,
tasks: TasksIcon,
trash: TrashIcon,
'trash-filled': TrashFilledIcon,
pin: PinIcon,
'pin-filled': PinFilledIcon,
unpin: UnpinIcon,
archive: ArchiveIcon,
unarchive: UnarchiveIcon,
Expand Down Expand Up @@ -130,11 +136,22 @@ export type IconType = keyof typeof ICONS;
type Props = {
type: IconType;
className?: string;
ariaLabel?: string;
};

export const Icon: FunctionalComponent<Props> = ({ type, className = '' }) => {
export const Icon: FunctionalComponent<Props> = ({
type,
className = '',
ariaLabel,
}) => {
const IconComponent = ICONS[type];
return <IconComponent className={`sn-icon ${className}`} />;
return (
<IconComponent
className={`sn-icon ${className}`}
role="img"
{...(ariaLabel ? { 'aria-label': ariaLabel } : {})}
/>
);
};

export const IconDirective = toDirective<Props>(Icon, {
Expand Down
32 changes: 20 additions & 12 deletions app/assets/javascripts/components/NotesList.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { WebApplication } from '@/ui_models/application';
import { KeyboardKey } from '@/services/ioService';
import { AppState } from '@/ui_models/app_state';
import { DisplayOptions } from '@/ui_models/app_state/notes_view_state';
Expand All @@ -7,6 +8,7 @@ import { FunctionComponent } from 'preact';
import { NotesListItem } from './NotesListItem';

type Props = {
application: WebApplication;
appState: AppState;
notes: SNNote[];
selectedNotes: Record<string, SNNote>;
Expand All @@ -18,23 +20,30 @@ const FOCUSABLE_BUT_NOT_TABBABLE = -1;
const NOTES_LIST_SCROLL_THRESHOLD = 200;

export const NotesList: FunctionComponent<Props> = observer(
({ appState, notes, selectedNotes, displayOptions, paginate }) => {
({
application,
appState,
notes,
selectedNotes,
displayOptions,
paginate,
}) => {
const { selectPreviousNote, selectNextNote } = appState.notesView;
const { hideTags, hideDate, hideNotePreview, sortBy } = displayOptions;

const tagsStringForNote = (note: SNNote): string => {
const tagsForNote = (note: SNNote): string[] => {
if (hideTags) {
return '';
return [];
}
const selectedTag = appState.selectedTag;
if (!selectedTag) {
return '';
return [];
}
const tags = appState.getNoteTags(note);
if (!selectedTag.isSmartTag && tags.length === 1) {
return '';
return [];
}
return tags.map((tag) => `#${tag.title}`).join(' ');
return tags.map((tag) => tag.title);
};

const openNoteContextMenu = (posX: number, posY: number) => {
Expand All @@ -46,11 +55,9 @@ export const NotesList: FunctionComponent<Props> = observer(
appState.notes.setContextMenuOpen(true);
};

const onContextMenu = async (note: SNNote, posX: number, posY: number) => {
await appState.notes.selectNote(note.uuid, true);
if (selectedNotes[note.uuid]) {
openNoteContextMenu(posX, posY);
}
const onContextMenu = (note: SNNote, posX: number, posY: number) => {
appState.notes.selectNote(note.uuid, true);
openNoteContextMenu(posX, posY);
};

const onScroll = (e: Event) => {
Expand Down Expand Up @@ -84,9 +91,10 @@ export const NotesList: FunctionComponent<Props> = observer(
>
{notes.map((note) => (
<NotesListItem
application={application}
key={note.uuid}
note={note}
tags={tagsStringForNote(note)}
tags={tagsForNote(note)}
selected={!!selectedNotes[note.uuid]}
hideDate={hideDate}
hidePreview={hideNotePreview}
Expand Down
Loading

0 comments on commit 7dd4a60

Please sign in to comment.