fix: fix tags container width
This commit is contained in:
@@ -12,20 +12,23 @@ type Props = {
|
|||||||
appState: AppState;
|
appState: AppState;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TAGS_ROW_RIGHT_MARGIN = 92;
|
|
||||||
const TAGS_ROW_HEIGHT = 36;
|
const TAGS_ROW_HEIGHT = 36;
|
||||||
const MIN_OVERFLOW_TOP = 76;
|
const MIN_OVERFLOW_TOP = 76;
|
||||||
const TAGS_RIGHT_MARGIN = 8;
|
const TAG_RIGHT_MARGIN = 8;
|
||||||
|
|
||||||
const NoteTags = observer(({ application, appState }: Props) => {
|
const NoteTags = observer(({ application, appState }: Props) => {
|
||||||
const { tags, tagsContainerPosition, tagsContainerMaxWidth } =
|
const {
|
||||||
appState.activeNote;
|
overflowedTagsCount,
|
||||||
|
tags,
|
||||||
|
tagsContainerPosition,
|
||||||
|
tagsContainerMaxWidth,
|
||||||
|
tagsContainerCollapsed,
|
||||||
|
tagsOverflowed,
|
||||||
|
} = appState.activeNote;
|
||||||
|
|
||||||
const [tagsContainerCollapsed, setTagsContainerCollapsed] = useState(true);
|
|
||||||
const [tagsContainerHeight, setTagsContainerHeight] =
|
const [tagsContainerHeight, setTagsContainerHeight] =
|
||||||
useState(TAGS_ROW_HEIGHT);
|
useState(TAGS_ROW_HEIGHT);
|
||||||
const [overflowCountPosition, setOverflowCountPosition] = useState(0);
|
const [overflowCountPosition, setOverflowCountPosition] = useState(0);
|
||||||
const [overflowCount, setOverflowCount] = useState(0);
|
|
||||||
|
|
||||||
const tagsContainerRef = useRef<HTMLDivElement>();
|
const tagsContainerRef = useRef<HTMLDivElement>();
|
||||||
const tagsRef = useRef<HTMLButtonElement[]>([]);
|
const tagsRef = useRef<HTMLButtonElement[]>([]);
|
||||||
@@ -39,7 +42,7 @@ const NoteTags = observer(({ application, appState }: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const expandTags = () => {
|
const expandTags = () => {
|
||||||
setTagsContainerCollapsed(false);
|
appState.activeNote.setTagsContainerCollapsed(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isTagOverflowed = useCallback(
|
const isTagOverflowed = useCallback(
|
||||||
@@ -65,7 +68,7 @@ const NoteTags = observer(({ application, appState }: Props) => {
|
|||||||
const previousTagRect =
|
const previousTagRect =
|
||||||
tagsRef.current[firstOverflowedTagIndex - 1].getBoundingClientRect();
|
tagsRef.current[firstOverflowedTagIndex - 1].getBoundingClientRect();
|
||||||
const position =
|
const position =
|
||||||
previousTagRect.right - (tagsContainerPosition ?? 0) + TAGS_RIGHT_MARGIN;
|
previousTagRect.right - (tagsContainerPosition ?? 0) + TAG_RIGHT_MARGIN;
|
||||||
setOverflowCountPosition(position);
|
setOverflowCountPosition(position);
|
||||||
}, [isTagOverflowed, tagsContainerCollapsed, tagsContainerPosition]);
|
}, [isTagOverflowed, tagsContainerCollapsed, tagsContainerPosition]);
|
||||||
|
|
||||||
@@ -80,8 +83,8 @@ const NoteTags = observer(({ application, appState }: Props) => {
|
|||||||
const count = tagsRef.current.filter((tagElement) =>
|
const count = tagsRef.current.filter((tagElement) =>
|
||||||
isTagOverflowed(tagElement)
|
isTagOverflowed(tagElement)
|
||||||
).length;
|
).length;
|
||||||
setOverflowCount(count);
|
appState.activeNote.setOverflowedTagsCount(count);
|
||||||
}, [isTagOverflowed]);
|
}, [appState.activeNote, isTagOverflowed]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
appState.activeNote.reloadTagsContainerLayout();
|
appState.activeNote.reloadTagsContainerLayout();
|
||||||
@@ -97,9 +100,7 @@ const NoteTags = observer(({ application, appState }: Props) => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const tagClass = `bg-contrast border-0 rounded text-xs color-text py-1 pr-2 flex items-center
|
const tagClass = `bg-contrast border-0 rounded text-xs color-text py-1 pr-2 flex items-center
|
||||||
mt-2 mr-2 cursor-pointer hover:bg-secondary-contrast focus:bg-secondary-contrast`;
|
mt-2 cursor-pointer hover:bg-secondary-contrast focus:bg-secondary-contrast`;
|
||||||
|
|
||||||
const overflowedTags = tagsContainerCollapsed && overflowCount > 0;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex" style={{ height: tagsContainerHeight }}>
|
<div className="flex" style={{ height: tagsContainerHeight }}>
|
||||||
@@ -111,12 +112,11 @@ const NoteTags = observer(({ application, appState }: Props) => {
|
|||||||
style={{
|
style={{
|
||||||
maxWidth: tagsContainerMaxWidth,
|
maxWidth: tagsContainerMaxWidth,
|
||||||
height: TAGS_ROW_HEIGHT,
|
height: TAGS_ROW_HEIGHT,
|
||||||
marginRight: TAGS_ROW_RIGHT_MARGIN,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tags.map((tag: SNTag, index: number) => (
|
{tags.map((tag: SNTag, index: number) => (
|
||||||
<button
|
<button
|
||||||
className={`${tagClass} pl-1`}
|
className={`${tagClass} pl-1 mr-2`}
|
||||||
style={{ maxWidth: tagsContainerMaxWidth }}
|
style={{ maxWidth: tagsContainerMaxWidth }}
|
||||||
ref={(element) => {
|
ref={(element) => {
|
||||||
if (element) {
|
if (element) {
|
||||||
@@ -143,17 +143,17 @@ const NoteTags = observer(({ application, appState }: Props) => {
|
|||||||
application={application}
|
application={application}
|
||||||
appState={appState}
|
appState={appState}
|
||||||
tagsRef={tagsRef}
|
tagsRef={tagsRef}
|
||||||
tabIndex={overflowedTags ? -1 : 0}
|
tabIndex={tagsOverflowed ? -1 : 0}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{overflowCount > 1 && tagsContainerCollapsed && (
|
{overflowedTagsCount > 1 && tagsContainerCollapsed && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`${tagClass} pl-2 absolute`}
|
className={`${tagClass} pl-2 absolute`}
|
||||||
style={{ left: overflowCountPosition }}
|
style={{ left: overflowCountPosition }}
|
||||||
onClick={expandTags}
|
onClick={expandTags}
|
||||||
>
|
>
|
||||||
+{overflowCount}
|
+{overflowedTagsCount}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const NotesOptionsPanel = observer(({ appState }: Props) => {
|
|||||||
}}
|
}}
|
||||||
onBlur={closeOnBlur}
|
onBlur={closeOnBlur}
|
||||||
ref={buttonRef}
|
ref={buttonRef}
|
||||||
className="sn-icon-button mt-2"
|
className="sn-icon-button"
|
||||||
>
|
>
|
||||||
<VisuallyHidden>Actions</VisuallyHidden>
|
<VisuallyHidden>Actions</VisuallyHidden>
|
||||||
<Icon type="more" className="block" />
|
<Icon type="more" className="block" />
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
} from '@standardnotes/snjs';
|
} from '@standardnotes/snjs';
|
||||||
import {
|
import {
|
||||||
action,
|
action,
|
||||||
|
computed,
|
||||||
makeObservable,
|
makeObservable,
|
||||||
observable,
|
observable,
|
||||||
} from 'mobx';
|
} from 'mobx';
|
||||||
@@ -15,6 +16,8 @@ export class ActiveNoteState {
|
|||||||
tags: SNTag[] = [];
|
tags: SNTag[] = [];
|
||||||
tagsContainerPosition? = 0;
|
tagsContainerPosition? = 0;
|
||||||
tagsContainerMaxWidth: number | 'auto' = 'auto';
|
tagsContainerMaxWidth: number | 'auto' = 'auto';
|
||||||
|
tagsContainerCollapsed = true;
|
||||||
|
overflowedTagsCount = 0;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private application: WebApplication,
|
private application: WebApplication,
|
||||||
@@ -25,9 +28,15 @@ export class ActiveNoteState {
|
|||||||
tags: observable,
|
tags: observable,
|
||||||
tagsContainerPosition: observable,
|
tagsContainerPosition: observable,
|
||||||
tagsContainerMaxWidth: observable,
|
tagsContainerMaxWidth: observable,
|
||||||
|
tagsContainerCollapsed: observable,
|
||||||
|
overflowedTagsCount: observable,
|
||||||
|
|
||||||
|
tagsOverflowed: computed,
|
||||||
|
|
||||||
setTagsContainerPosition: action,
|
setTagsContainerPosition: action,
|
||||||
setTagsContainerMaxWidth: action,
|
setTagsContainerMaxWidth: action,
|
||||||
|
setTagsContainerCollapsed: action,
|
||||||
|
setOverflowedTagsCount: action,
|
||||||
reloadTags: action,
|
reloadTags: action,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -49,6 +58,10 @@ export class ActiveNoteState {
|
|||||||
return this.appState.notes.activeEditor?.note;
|
return this.appState.notes.activeEditor?.note;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get tagsOverflowed(): boolean {
|
||||||
|
return this.overflowedTagsCount > 0 && this.tagsContainerCollapsed;
|
||||||
|
}
|
||||||
|
|
||||||
setTagsContainerPosition(position: number): void {
|
setTagsContainerPosition(position: number): void {
|
||||||
this.tagsContainerPosition = position;
|
this.tagsContainerPosition = position;
|
||||||
}
|
}
|
||||||
@@ -57,6 +70,14 @@ export class ActiveNoteState {
|
|||||||
this.tagsContainerMaxWidth = width;
|
this.tagsContainerMaxWidth = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTagsContainerCollapsed(collapsed: boolean): void {
|
||||||
|
this.tagsContainerCollapsed = collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOverflowedTagsCount(count: number): void {
|
||||||
|
this.overflowedTagsCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
reloadTags(): void {
|
reloadTags(): void {
|
||||||
const { activeNote } = this;
|
const { activeNote } = this;
|
||||||
if (activeNote) {
|
if (activeNote) {
|
||||||
@@ -65,14 +86,15 @@ export class ActiveNoteState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reloadTagsContainerLayout(): void {
|
reloadTagsContainerLayout(): void {
|
||||||
const editorElementId = 'editor-column';
|
const MARGIN = this.tagsContainerCollapsed ? 68 : 24;
|
||||||
|
const EDITOR_ELEMENT_ID = 'editor-column';
|
||||||
const { clientWidth } = document.documentElement;
|
const { clientWidth } = document.documentElement;
|
||||||
const editorPosition =
|
const editorPosition =
|
||||||
document.getElementById(editorElementId)?.getBoundingClientRect()
|
document.getElementById(EDITOR_ELEMENT_ID)?.getBoundingClientRect()
|
||||||
.left ?? 0;
|
.left ?? 0;
|
||||||
this.appState.activeNote.setTagsContainerPosition(editorPosition);
|
this.appState.activeNote.setTagsContainerPosition(editorPosition);
|
||||||
this.appState.activeNote.setTagsContainerMaxWidth(
|
this.appState.activeNote.setTagsContainerMaxWidth(
|
||||||
clientWidth - editorPosition
|
clientWidth - editorPosition - MARGIN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,37 +24,38 @@
|
|||||||
ng-if="self.showLockedIcon"
|
ng-if="self.showLockedIcon"
|
||||||
)
|
)
|
||||||
| {{self.lockText}}
|
| {{self.lockText}}
|
||||||
#editor-title-bar.section-title-bar.flex.items-start.justify-between.w-full(
|
#editor-title-bar.section-title-bar.w-full(
|
||||||
ng-show='self.note && !self.note.errorDecrypting'
|
ng-show='self.note && !self.note.errorDecrypting'
|
||||||
)
|
)
|
||||||
div.flex-grow(
|
div.flex.items-start.justify-between
|
||||||
ng-class="{'locked' : self.noteLocked}"
|
div.flex-grow(
|
||||||
|
ng-class="{'locked' : self.noteLocked}"
|
||||||
|
)
|
||||||
|
.title.overflow-auto
|
||||||
|
input#note-title-editor.input(
|
||||||
|
ng-blur='self.onTitleBlur()',
|
||||||
|
ng-change='self.onTitleChange()',
|
||||||
|
ng-disabled='self.noteLocked',
|
||||||
|
ng-focus='self.onTitleFocus()',
|
||||||
|
ng-keyup='$event.keyCode == 13 && self.onTitleEnter($event)',
|
||||||
|
ng-model='self.editorValues.title',
|
||||||
|
select-on-focus='true',
|
||||||
|
spellcheck='false'
|
||||||
|
)
|
||||||
|
div.flex.items-center
|
||||||
|
#save-status
|
||||||
|
.message(
|
||||||
|
ng-class="{'warning sk-bold': self.state.syncTakingTooLong, 'danger sk-bold': self.state.saveError}"
|
||||||
|
) {{self.state.noteStatus.message}}
|
||||||
|
.desc(ng-show='self.state.noteStatus.desc') {{self.state.noteStatus.desc}}
|
||||||
|
notes-options-panel(
|
||||||
|
app-state='self.appState',
|
||||||
|
ng-if='self.appState.notes.selectedNotesCount > 0'
|
||||||
|
)
|
||||||
|
note-tags(
|
||||||
|
application='self.application'
|
||||||
|
app-state='self.appState'
|
||||||
)
|
)
|
||||||
.title.overflow-auto
|
|
||||||
input#note-title-editor.input(
|
|
||||||
ng-blur='self.onTitleBlur()',
|
|
||||||
ng-change='self.onTitleChange()',
|
|
||||||
ng-disabled='self.noteLocked',
|
|
||||||
ng-focus='self.onTitleFocus()',
|
|
||||||
ng-keyup='$event.keyCode == 13 && self.onTitleEnter($event)',
|
|
||||||
ng-model='self.editorValues.title',
|
|
||||||
select-on-focus='true',
|
|
||||||
spellcheck='false'
|
|
||||||
)
|
|
||||||
note-tags(
|
|
||||||
application='self.application'
|
|
||||||
app-state='self.appState'
|
|
||||||
)
|
|
||||||
div.flex.items-center
|
|
||||||
#save-status
|
|
||||||
.message(
|
|
||||||
ng-class="{'warning sk-bold': self.state.syncTakingTooLong, 'danger sk-bold': self.state.saveError}"
|
|
||||||
) {{self.state.noteStatus.message}}
|
|
||||||
.desc(ng-show='self.state.noteStatus.desc') {{self.state.noteStatus.desc}}
|
|
||||||
notes-options-panel(
|
|
||||||
app-state='self.appState',
|
|
||||||
ng-if='self.appState.notes.selectedNotesCount > 0'
|
|
||||||
)
|
|
||||||
.sn-component(ng-if='self.note')
|
.sn-component(ng-if='self.note')
|
||||||
#editor-menu-bar.sk-app-bar.no-edges
|
#editor-menu-bar.sk-app-bar.no-edges
|
||||||
.left
|
.left
|
||||||
|
|||||||
Reference in New Issue
Block a user