From 1c6f5b9be8d118ed6f02e09952a04aa80d4c6461 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Tue, 21 Dec 2021 12:25:14 +0100 Subject: [PATCH 1/7] fix: upgrade design after review * fix: tweak dropzone * fix: sync after assign parent * fix: tsc error on build * fix: vertical center the fold arrows * fix: define our own hoist for react-dnd * feat: hide fold when there are no folders * fix: show children usability + resize UI * fix: use old colors for now, theme compat --- .../QuickSettingsMenu/QuickSettingsMenu.tsx | 1 - .../components/RootTagDropZone.tsx | 7 +- .../components/Tags/TagsSection.tsx | 1 + .../javascripts/components/TagsListItem.tsx | 30 +++++---- .../typings/hoist-non-react-statics.d.ts | 67 +++++++++++++++++++ .../ui_models/app_state/tags_state.ts | 15 ++++- app/assets/stylesheets/_tags.scss | 40 ++++++++--- 7 files changed, 134 insertions(+), 27 deletions(-) create mode 100644 app/assets/javascripts/typings/hoist-non-react-statics.d.ts diff --git a/app/assets/javascripts/components/QuickSettingsMenu/QuickSettingsMenu.tsx b/app/assets/javascripts/components/QuickSettingsMenu/QuickSettingsMenu.tsx index 701be49dc35..045e3f49250 100644 --- a/app/assets/javascripts/components/QuickSettingsMenu/QuickSettingsMenu.tsx +++ b/app/assets/javascripts/components/QuickSettingsMenu/QuickSettingsMenu.tsx @@ -23,7 +23,6 @@ import { themesMenuKeyDownHandler, } from './eventHandlers'; import { FocusModeSwitch } from './FocusModeSwitch'; -import { TagNestingSwitch } from './TagNestingSwitch'; import { ThemesMenuButton } from './ThemesMenuButton'; const focusModeAnimationDuration = 1255; diff --git a/app/assets/javascripts/components/RootTagDropZone.tsx b/app/assets/javascripts/components/RootTagDropZone.tsx index 67e510f68f0..de49a242e13 100644 --- a/app/assets/javascripts/components/RootTagDropZone.tsx +++ b/app/assets/javascripts/components/RootTagDropZone.tsx @@ -5,6 +5,7 @@ import { import { TagsState } from '@/ui_models/app_state/tags_state'; import { observer } from 'mobx-react-lite'; import { useDrop } from 'react-dnd'; +import { Icon } from './Icon'; import { usePremiumModal } from './Premium'; import { DropItem, DropProps, ItemTypes } from './TagsListItem'; @@ -52,7 +53,11 @@ export const RootTagDropZone: React.FC = observer( isOver ? 'is-over' : '' }`} > - Move the tag here to remove it from its folder. + +

+ Move the tag here to
+ remove it from its folder. +

); } diff --git a/app/assets/javascripts/components/Tags/TagsSection.tsx b/app/assets/javascripts/components/Tags/TagsSection.tsx index a0064e1015c..5cc7a452db8 100644 --- a/app/assets/javascripts/components/Tags/TagsSection.tsx +++ b/app/assets/javascripts/components/Tags/TagsSection.tsx @@ -33,6 +33,7 @@ const TagAddButton: FunctionComponent<{ appState.createNewTag()} /> ); diff --git a/app/assets/javascripts/components/TagsListItem.tsx b/app/assets/javascripts/components/TagsListItem.tsx index b41ea1653e0..859e2802dd5 100644 --- a/app/assets/javascripts/components/TagsListItem.tsx +++ b/app/assets/javascripts/components/TagsListItem.tsx @@ -42,7 +42,6 @@ export type TagsListState = { export const TagsListItem: FunctionComponent = observer( ({ tag, selectTag, saveTag, removeTag, appState, tagsState, level }) => { const [title, setTitle] = useState(tag.title || ''); - const [showChildren, setShowChildren] = useState(true); const inputRef = useRef(null); const isSelected = appState.selectedTag === tag; @@ -54,8 +53,19 @@ export const TagsListItem: FunctionComponent = observer( const hasFolders = tagsState.hasFolders; const isNativeFoldersEnabled = appState.features.enableNativeFoldersFeature; + const hasAtLeastOneFolder = tagsState.hasAtLeastOneFolder; const premiumModal = usePremiumModal(); + const [showChildren, setShowChildren] = useState(hasChildren); + const [hadChildren, setHadChildren] = useState(hasChildren); + + useEffect(() => { + if (!hadChildren && hasChildren) { + setShowChildren(true); + } + setHadChildren(hasChildren); + }, [hadChildren, hasChildren]); + useEffect(() => { setTitle(tag.title || ''); }, [setTitle, tag]); @@ -167,21 +177,17 @@ export const TagsListItem: FunctionComponent = observer( > {!tag.errorDecrypting ? (
- {hasFolders && isNativeFoldersEnabled && ( + {hasFolders && isNativeFoldersEnabled && hasAtLeastOneFolder && (
- {hasChildren && ( - - )} +
)}
, James Reggio +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 +// https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/hoist-non-react-statics + +declare module 'hoist-non-react-statics' { + interface REACT_STATICS { + childContextTypes: true; + contextType: true; + contextTypes: true; + defaultProps: true; + displayName: true; + getDefaultProps: true; + getDerivedStateFromError: true; + getDerivedStateFromProps: true; + mixins: true; + propTypes: true; + type: true; + } + + interface KNOWN_STATICS { + name: true; + length: true; + prototype: true; + caller: true; + callee: true; + arguments: true; + arity: true; + } + + interface MEMO_STATICS { + $$typeof: true; + compare: true; + defaultProps: true; + displayName: true; + propTypes: true; + type: true; + } + + interface FORWARD_REF_STATICS { + $$typeof: true; + render: true; + defaultProps: true; + displayName: true; + propTypes: true; + } + + export type NonReactStatics< + S extends React.ComponentType, + C extends { + [key: string]: true; + } = {} + > = { + [key in Exclude< + keyof S, + S extends React.MemoExoticComponent + ? keyof MEMO_STATICS | keyof C + : S extends React.ForwardRefExoticComponent + ? keyof FORWARD_REF_STATICS | keyof C + : keyof REACT_STATICS | keyof KNOWN_STATICS | keyof C + >]: S[key]; + }; +} diff --git a/app/assets/javascripts/ui_models/app_state/tags_state.ts b/app/assets/javascripts/ui_models/app_state/tags_state.ts index c068692aa56..222d6afc9c5 100644 --- a/app/assets/javascripts/ui_models/app_state/tags_state.ts +++ b/app/assets/javascripts/ui_models/app_state/tags_state.ts @@ -70,17 +70,22 @@ export class TagsState { return this.application.isValidTagParent(parentUuid, tagUuid); } - assignParent(tagUuid: string, parentUuid: string | undefined): void { + public async assignParent( + tagUuid: string, + parentUuid: string | undefined + ): Promise { const tag = this.application.findItem(tagUuid) as SNTag; const parent = parentUuid && (this.application.findItem(parentUuid) as SNTag); if (!parent) { - this.application.unsetTagParent(tag); + await this.application.unsetTagParent(tag); } else { - this.application.setTagParent(parent, tag); + await this.application.setTagParent(parent, tag); } + + await this.application.sync(); } get rootTags(): SNTag[] { @@ -102,4 +107,8 @@ export class TagsState { public set hasFolders(hasFolders: boolean) { this.features.hasFolders = hasFolders; } + + public get hasAtLeastOneFolder(): boolean { + return this.tags.some((tag) => !!this.application.getTagParent(tag)); + } } diff --git a/app/assets/stylesheets/_tags.scss b/app/assets/stylesheets/_tags.scss index 14d9626dfb4..07953364b54 100644 --- a/app/assets/stylesheets/_tags.scss +++ b/app/assets/stylesheets/_tags.scss @@ -53,10 +53,19 @@ .root-drop { width: '100%'; - padding: 10px; + padding: 12px; opacity: 0; transition: opacity 0.3s ease-in; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + + .sn-icon { + margin-right: 0.5rem; + } + &.active { opacity: 1; @@ -81,11 +90,26 @@ align-items: center; justify-content: space-between; - > .tag-icon { - svg { - display: block; - margin: auto; + .sn-icon { + display: block; + margin: 0 auto; + + &.hidden { + visibility: hidden; } + } + + > .tag-fold { + width: 22px; + display: flex; + align-items: center; + height: 100%; + } + + > .tag-icon { + display: flex; + align-items: center; + height: 100%; &.draggable { cursor: move; @@ -96,10 +120,6 @@ } } - > .tag-fold { - width: 22px; - } - > .title { @extend .focus\:outline-none; @extend .focus\:shadow-none; @@ -179,7 +199,7 @@ &:hover:not(.selected), &.selected, &.is-drag-over { - background-color: var(--sn-stylekit-white); + background-color: var(--sn-stylekit-secondary-contrast-background-color); color: var(--sn-stylekit-secondary-contrast-foreground-color); > .title { From 0ed428aad0be670761bf869cf8517589e56db6a7 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 22 Dec 2021 11:05:23 +0100 Subject: [PATCH 2/7] fix: tweak alignment and add title --- app/assets/javascripts/components/TagsListItem.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/components/TagsListItem.tsx b/app/assets/javascripts/components/TagsListItem.tsx index 859e2802dd5..471a5a4b569 100644 --- a/app/assets/javascripts/components/TagsListItem.tsx +++ b/app/assets/javascripts/components/TagsListItem.tsx @@ -173,10 +173,10 @@ export const TagsListItem: FunctionComponent = observer( }`} onClick={selectCurrentTag} ref={dragRef} - style={{ paddingLeft: `${level + 0.5}rem` }} + style={{ paddingLeft: `${level * 21 + 10}px` }} > {!tag.errorDecrypting ? ( -
+
{hasFolders && isNativeFoldersEnabled && hasAtLeastOneFolder && (
Date: Wed, 22 Dec 2021 11:27:14 +0100 Subject: [PATCH 3/7] fix: meta offset with folders --- app/assets/javascripts/components/TagsListItem.tsx | 2 +- app/assets/stylesheets/_tags.scss | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/components/TagsListItem.tsx b/app/assets/javascripts/components/TagsListItem.tsx index 471a5a4b569..ac725aa3a55 100644 --- a/app/assets/javascripts/components/TagsListItem.tsx +++ b/app/assets/javascripts/components/TagsListItem.tsx @@ -214,7 +214,7 @@ export const TagsListItem: FunctionComponent = observer(
{noteCounts}
) : null} -
+
{tag.conflictOf && (
Conflicted Copy {tag.conflictOf} diff --git a/app/assets/stylesheets/_tags.scss b/app/assets/stylesheets/_tags.scss index 07953364b54..f62e9dbf902 100644 --- a/app/assets/stylesheets/_tags.scss +++ b/app/assets/stylesheets/_tags.scss @@ -167,7 +167,11 @@ } .meta { - padding-left: 20px; + padding-left: 3px; + + &.with-folders { + padding-left: 25px; + } > .menu { font-size: 11px; From 32eb98f074304cfa1be36a582c5bcd2a16f695f6 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 22 Dec 2021 14:19:12 +0100 Subject: [PATCH 4/7] fix: tweak tag size --- app/assets/stylesheets/_tags.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/stylesheets/_tags.scss b/app/assets/stylesheets/_tags.scss index f62e9dbf902..ae38f530977 100644 --- a/app/assets/stylesheets/_tags.scss +++ b/app/assets/stylesheets/_tags.scss @@ -77,6 +77,9 @@ } .tag { + font-size: 14px; + line-height: 18px; + min-height: 30px; padding: 5px 12px; cursor: pointer; From 2ca1a4a9f9efc7bdc2aa7e341a58c66456c65046 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 22 Dec 2021 14:22:18 +0100 Subject: [PATCH 5/7] fix: observable setup --- app/assets/javascripts/ui_models/app_state/tags_state.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/ui_models/app_state/tags_state.ts b/app/assets/javascripts/ui_models/app_state/tags_state.ts index 222d6afc9c5..80c38edd5ca 100644 --- a/app/assets/javascripts/ui_models/app_state/tags_state.ts +++ b/app/assets/javascripts/ui_models/app_state/tags_state.ts @@ -24,9 +24,10 @@ export class TagsState { private features: FeaturesState ) { makeObservable(this, { - tags: observable, - smartTags: observable, + tags: observable.ref, + smartTags: observable.ref, hasFolders: computed, + hasAtLeastOneFolder: computed, assignParent: action, From d362f7c02889dfbcc4c3e009bee8e5b0dbbb9ea8 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 22 Dec 2021 14:32:47 +0100 Subject: [PATCH 6/7] fix: use link-off icon on dropzone --- app/assets/icons/ic-link-off.svg | 3 +++ app/assets/javascripts/components/Icon.tsx | 2 ++ app/assets/javascripts/components/RootTagDropZone.tsx | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 app/assets/icons/ic-link-off.svg diff --git a/app/assets/icons/ic-link-off.svg b/app/assets/icons/ic-link-off.svg new file mode 100644 index 00000000000..3b701266cd7 --- /dev/null +++ b/app/assets/icons/ic-link-off.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/javascripts/components/Icon.tsx b/app/assets/javascripts/components/Icon.tsx index c296e00a2d1..96eee992f8e 100644 --- a/app/assets/javascripts/components/Icon.tsx +++ b/app/assets/javascripts/components/Icon.tsx @@ -55,6 +55,7 @@ import LockIcon from '../../icons/ic-lock.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'; +import LinkOffIcon from '../../icons/ic-link-off.svg'; import MenuArrowDownAlt from '../../icons/ic-menu-arrow-down-alt.svg'; import MenuArrowRight from '../../icons/ic-menu-arrow-right.svg'; @@ -105,6 +106,7 @@ const ICONS = { help: HelpIcon, keyboard: KeyboardIcon, 'list-bulleted': ListBulleted, + 'link-off': LinkOffIcon, listed: ListedIcon, security: SecurityIcon, settings: SettingsIcon, diff --git a/app/assets/javascripts/components/RootTagDropZone.tsx b/app/assets/javascripts/components/RootTagDropZone.tsx index de49a242e13..0e39ef5a829 100644 --- a/app/assets/javascripts/components/RootTagDropZone.tsx +++ b/app/assets/javascripts/components/RootTagDropZone.tsx @@ -53,7 +53,7 @@ export const RootTagDropZone: React.FC = observer( isOver ? 'is-over' : '' }`} > - +

Move the tag here to
remove it from its folder. From 5172a565ca08573c39c7dd67c1e93e9077ca4303 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 22 Dec 2021 14:56:30 +0100 Subject: [PATCH 7/7] fix: more tweak on text sizes --- app/assets/stylesheets/_tags.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/stylesheets/_tags.scss b/app/assets/stylesheets/_tags.scss index ae38f530977..e44610a4462 100644 --- a/app/assets/stylesheets/_tags.scss +++ b/app/assets/stylesheets/_tags.scss @@ -126,6 +126,9 @@ > .title { @extend .focus\:outline-none; @extend .focus\:shadow-none; + font-size: 14px; + line-height: 18px; + width: 80%; background-color: transparent; font-weight: 600;