diff --git a/app/assets/icons/ic-chevron-right.svg b/app/assets/icons/ic-chevron-right.svg
new file mode 100644
index 000000000..862c72f97
--- /dev/null
+++ b/app/assets/icons/ic-chevron-right.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/assets/icons/ic-hashtag.svg b/app/assets/icons/ic-hashtag.svg
new file mode 100644
index 000000000..5d9333ec1
--- /dev/null
+++ b/app/assets/icons/ic-hashtag.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/assets/javascripts/components/Icon.tsx b/app/assets/javascripts/components/Icon.tsx
index fee3b436a..f11c5d262 100644
--- a/app/assets/javascripts/components/Icon.tsx
+++ b/app/assets/javascripts/components/Icon.tsx
@@ -5,6 +5,8 @@ import PinIcon from '../../icons/ic-pin.svg';
import UnpinIcon from '../../icons/ic-pin-off.svg';
import ArchiveIcon from '../../icons/ic-archive.svg';
import UnarchiveIcon from '../../icons/ic-unarchive.svg';
+import HashtagIcon from '../../icons/ic-hashtag.svg';
+import ChevronRightIcon from '../../icons/ic-chevron-right.svg';
import { toDirective } from './utils';
export enum IconType {
@@ -14,7 +16,9 @@ export enum IconType {
Pin = 'pin',
Unpin = 'unpin',
Archive = 'archive',
- Unarchive = 'unarchive'
+ Unarchive = 'unarchive',
+ Hashtag = 'hashtag',
+ ChevronRight = 'chevron-right',
}
const ICONS = {
@@ -24,7 +28,9 @@ const ICONS = {
[IconType.Pin]: PinIcon,
[IconType.Unpin]: UnpinIcon,
[IconType.Archive]: ArchiveIcon,
- [IconType.Unarchive]: UnarchiveIcon
+ [IconType.Unarchive]: UnarchiveIcon,
+ [IconType.Hashtag]: HashtagIcon,
+ [IconType.ChevronRight]: ChevronRightIcon,
};
type Props = {
diff --git a/app/assets/javascripts/components/NotesOptions.tsx b/app/assets/javascripts/components/NotesOptions.tsx
index ebed8810e..5b1c5c698 100644
--- a/app/assets/javascripts/components/NotesOptions.tsx
+++ b/app/assets/javascripts/components/NotesOptions.tsx
@@ -2,7 +2,12 @@ import { AppState } from '@/ui_models/app_state';
import { Icon, IconType } from './Icon';
import { Switch } from './Switch';
import { observer } from 'mobx-react-lite';
-import { useRef } from 'preact/hooks';
+import { useRef, useState } from 'preact/hooks';
+import {
+ Disclosure,
+ DisclosureButton,
+ DisclosurePanel,
+} from '@reach/disclosure';
type Props = {
appState: AppState;
@@ -12,6 +17,12 @@ type Props = {
export const NotesOptions = observer(
({ appState, closeOnBlur, setLockCloseOnBlur }: Props) => {
+ const [tagsMenuOpen, setTagsMenuOpen] = useState(false);
+ const [tagsMenuPosition, setTagsMenuPosition] = useState({
+ top: 0,
+ right: 0,
+ });
+
const notes = Object.values(appState.notes.selectedNotes);
const hidePreviews = !notes.some((note) => !note.hidePreview);
const locked = !notes.some((note) => !note.locked);
@@ -20,6 +31,7 @@ export const NotesOptions = observer(
const pinned = !notes.some((note) => !note.pinned);
const trashButtonRef = useRef();
+ const tagsButtonRef = useRef();
const iconClass = 'fill-current color-neutral mr-2';
const buttonClass =
@@ -56,6 +68,60 @@ export const NotesOptions = observer(
+ {
+ const buttonRect = tagsButtonRef.current.getBoundingClientRect();
+ const { offsetTop, offsetWidth } = tagsButtonRef.current;
+ setTagsMenuPosition({
+ top: offsetTop,
+ right: ((buttonRect.right + 265) > document.body.clientWidth) ? offsetWidth : -offsetWidth,
+ });
+ setTagsMenuOpen(!tagsMenuOpen);
+ }}
+ >
+ {
+ if (event.key === 'Escape') {
+ setTagsMenuOpen(false);
+ }
+ }}
+ onBlur={closeOnBlur}
+ ref={tagsButtonRef}
+ className={`${buttonClass} justify-between`}
+ >
+
+
+ {"Add tag"}
+
+
+
+ {
+ if (event.key === 'Escape') {
+ setTagsMenuOpen(false);
+ tagsButtonRef.current.focus();
+ }
+ }}
+ style={{
+ ...tagsMenuPosition
+ }}
+ className="sn-dropdown sn-dropdown-anchor-right flex flex-col py-2 max-w-265"
+ >
+ {appState.tags.tags.map(tag => (
+
+ ))}
+
+