Skip to content

Commit 65f5062

Browse files
olaurendeauAntoLC
authored andcommitted
✨(frontend) add EmojiPicker in DocumentTitle
We can now add emojis to the document title using the EmojiPicker component.
1 parent 681138e commit 65f5062

File tree

9 files changed

+155
-60
lines changed

9 files changed

+155
-60
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ and this project adheres to
4949
### Added
5050

5151
- ✨(api) add API route to fetch document content #1206
52+
- ✨(frontend) doc emojis improvements #1381
53+
- add an EmojiPicker in the document tree and document title
54+
- remove emoji buttons in menus
5255

5356
### Changed
5457

@@ -62,6 +65,8 @@ and this project adheres to
6265
- ✨unify tab focus style for better visual consistency #1341
6366
- ♿hide decorative icons, label menus, avoid accessible name… #1362
6467
- ♻️(tilt) use helm dev-backend chart
68+
- 🩹(frontend) on main pages do not display leading emoji as page icon #1381
69+
- 🩹(frontend) handle properly emojis in interlinking #1381
6570

6671
### Removed
6772

src/frontend/apps/impress/src/features/docs/doc-editor/components/EmojiPicker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const EmojiPicker = ({
1919
const { i18n } = useTranslation();
2020

2121
return (
22-
<Box>
22+
<Box $position="absolute" $zIndex={1000} $margin="2rem 0 0 0">
2323
<Picker
2424
data={emojiData}
2525
locale={i18n.resolvedLanguage}

src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/InterlinkingLinkInlineContent.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,17 @@ const LinkSelected = ({ url, title }: LinkSelectedProps) => {
7373
transition: background-color 0.2s ease-in-out;
7474
`}
7575
>
76-
<Box $display="inline-block" $css={css`margin-right: 0.3rem; `}>
77-
{emoji ? <Icon iconName={emoji} $size="16px" /> : <SelectedPageIcon width={11.5}/>}
76+
<Box
77+
$display="inline-block"
78+
$css={css`
79+
margin-right: 0.3rem;
80+
`}
81+
>
82+
{emoji ? (
83+
<Icon iconName={emoji} $size="16px" />
84+
) : (
85+
<SelectedPageIcon width={11.5} />
86+
)}
7887
</Box>
7988
<Text $weight="500" spellCheck="false" $size="16px" $display="inline">
8089
{titleWithoutEmoji}

src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx

Lines changed: 82 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ import { Box, Text } from '@/components';
77
import { useCunninghamTheme } from '@/cunningham';
88
import {
99
Doc,
10+
DocIcon,
11+
getEmojiAndTitle,
1012
useDocStore,
1113
useDocTitleUpdate,
1214
useIsCollaborativeEditable,
1315
useTrans,
1416
} from '@/docs/doc-management';
17+
import SimpleFileIcon from '@/features/docs/doc-management/assets/simple-document.svg';
1518
import { useResponsiveStore } from '@/stores';
1619

1720
interface DocTitleProps {
@@ -50,18 +53,26 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
5053
const { isDesktop } = useResponsiveStore();
5154
const { t } = useTranslation();
5255
const { colorsTokens } = useCunninghamTheme();
53-
const [titleDisplay, setTitleDisplay] = useState(doc.title);
56+
const { emoji, titleWithoutEmoji } = getEmojiAndTitle(doc.title ?? '');
57+
const { spacingsTokens } = useCunninghamTheme();
5458

5559
const { untitledDocument } = useTrans();
60+
const [titleDisplay, setTitleDisplay] = useState(titleWithoutEmoji);
5661

5762
const { updateDocTitle } = useDocTitleUpdate();
5863

5964
const handleTitleSubmit = useCallback(
6065
(inputText: string) => {
61-
const sanitizedTitle = updateDocTitle(doc, inputText.trim());
62-
setTitleDisplay(sanitizedTitle);
66+
const sanitizedTitle = updateDocTitle(
67+
doc,
68+
emoji ? `${emoji} ${inputText.trim()}` : inputText.trim(),
69+
);
70+
const { titleWithoutEmoji: sanitizedTitleWithoutEmoji } =
71+
getEmojiAndTitle(sanitizedTitle);
72+
73+
setTitleDisplay(sanitizedTitleWithoutEmoji);
6374
},
64-
[doc, updateDocTitle],
75+
[doc, updateDocTitle, emoji],
6576
);
6677

6778
const handleKeyDown = (e: React.KeyboardEvent) => {
@@ -72,43 +83,75 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
7283
};
7384

7485
useEffect(() => {
75-
setTitleDisplay(doc.title);
76-
}, [doc]);
86+
setTitleDisplay(titleWithoutEmoji);
87+
}, [doc, titleWithoutEmoji]);
7788

7889
return (
79-
<Tooltip content={t('Rename')} aria-hidden={true} placement="top">
80-
<Box
81-
as="span"
82-
role="textbox"
83-
className="--docs--doc-title-input"
84-
contentEditable
85-
defaultValue={titleDisplay || undefined}
86-
onKeyDownCapture={handleKeyDown}
87-
suppressContentEditableWarning={true}
88-
aria-label={`${t('Document title')}`}
89-
aria-multiline={false}
90-
onBlurCapture={(event) =>
91-
handleTitleSubmit(event.target.textContent || '')
92-
}
93-
$color={colorsTokens['greyscale-1000']}
94-
$minHeight="40px"
95-
$padding={{ right: 'big' }}
96-
$css={css`
97-
&[contenteditable='true']:empty:not(:focus):before {
98-
content: '${untitledDocument}';
99-
color: grey;
100-
pointer-events: none;
101-
font-style: italic;
90+
<Box
91+
$direction="row"
92+
$align="flex-end"
93+
$gap={spacingsTokens['s']}
94+
$minHeight="40px"
95+
>
96+
<Tooltip content={t('Document emoji')} aria-hidden={true} placement="top">
97+
<Box
98+
$css={css`
99+
height: 58px;
100+
cursor: pointer;
101+
`}
102+
>
103+
<DocIcon
104+
emojiPicker
105+
docId={doc.id}
106+
title={doc.title}
107+
emoji={emoji}
108+
$size="50px"
109+
defaultIcon={
110+
<SimpleFileIcon
111+
width="50px"
112+
height="50px"
113+
aria-hidden="true"
114+
aria-label={t('Simple document icon')}
115+
color={colorsTokens['primary-500']}
116+
/>
117+
}
118+
/>
119+
</Box>
120+
</Tooltip>
121+
122+
<Tooltip content={t('Rename')} aria-hidden={true} placement="top">
123+
<Box
124+
as="span"
125+
role="textbox"
126+
className="--docs--doc-title-input"
127+
contentEditable
128+
defaultValue={titleDisplay || undefined}
129+
onKeyDownCapture={handleKeyDown}
130+
suppressContentEditableWarning={true}
131+
aria-label={`${t('Document title')}`}
132+
aria-multiline={false}
133+
onBlurCapture={(event) =>
134+
handleTitleSubmit(event.target.textContent || '')
102135
}
103-
font-size: ${isDesktop
104-
? css`var(--c--theme--font--sizes--h2)`
105-
: css`var(--c--theme--font--sizes--sm)`};
106-
font-weight: 700;
107-
outline: none;
108-
`}
109-
>
110-
{titleDisplay}
111-
</Box>
112-
</Tooltip>
136+
$color={colorsTokens['greyscale-1000']}
137+
$padding={{ right: 'big' }}
138+
$css={css`
139+
&[contenteditable='true']:empty:not(:focus):before {
140+
content: '${untitledDocument}';
141+
color: grey;
142+
pointer-events: none;
143+
font-style: italic;
144+
}
145+
font-size: ${isDesktop
146+
? css`var(--c--theme--font--sizes--h2)`
147+
: css`var(--c--theme--font--sizes--sm)`};
148+
font-weight: 700;
149+
outline: none;
150+
`}
151+
>
152+
{titleDisplay}
153+
</Box>
154+
</Tooltip>
155+
</Box>
113156
);
114157
};

src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
KEY_DOC,
2121
KEY_LIST_DOC,
2222
ModalRemoveDoc,
23+
getEmojiAndTitle,
2324
useCopyDocLink,
2425
useCreateFavoriteDoc,
2526
useDeleteFavoriteDoc,
@@ -33,6 +34,7 @@ import {
3334
import { useAnalytics } from '@/libs';
3435
import { useResponsiveStore } from '@/stores';
3536

37+
import { useDocTitleUpdate } from '../../doc-management/hooks/useDocTitleUpdate';
3638
import { useCopyCurrentEditorToClipboard } from '../hooks/useCopyCurrentEditorToClipboard';
3739

3840
const ModalExport = Export?.ModalExport;
@@ -92,6 +94,13 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
9294
});
9395
}, [selectHistoryModal.isOpen, queryClient]);
9496

97+
// Emoji Management
98+
const { emoji } = getEmojiAndTitle(doc.title ?? '');
99+
const { updateDocEmoji } = useDocTitleUpdate();
100+
const removeEmoji = () => {
101+
updateDocEmoji(doc.id, doc.title ?? '', '');
102+
};
103+
95104
const options: DropdownMenuOption[] = [
96105
...(isSmallMobile
97106
? [
@@ -127,6 +136,15 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
127136
},
128137
testId: `docs-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`,
129138
},
139+
...(emoji
140+
? [
141+
{
142+
label: t('Remove emoji'),
143+
icon: 'emoji_emotions',
144+
callback: removeEmoji,
145+
},
146+
]
147+
: []),
130148
{
131149
label: t('Version history'),
132150
icon: 'history',

src/frontend/apps/impress/src/features/docs/doc-management/assets/simple-document.svg

Lines changed: 0 additions & 2 deletions
Loading

src/frontend/apps/impress/src/features/docs/doc-management/components/SimpleDocItem.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import { useResponsiveStore } from '@/stores';
1010
import PinnedDocumentIcon from '../assets/pinned-document.svg';
1111
import SimpleFileIcon from '../assets/simple-document.svg';
1212

13-
import { DocIcon } from './DocIcon';
14-
1513
const ItemTextCss = css`
1614
overflow: hidden;
1715
text-overflow: ellipsis;
@@ -66,16 +64,12 @@ export const SimpleDocItem = ({
6664
color={colorsTokens['primary-500']}
6765
/>
6866
) : (
69-
<DocIcon
70-
defaultIcon={
71-
<SimpleFileIcon
72-
aria-hidden="true"
73-
data-testid="doc-simple-icon"
74-
color={colorsTokens['primary-500']}
75-
/>
76-
}
77-
$size="25px"
78-
docId={doc.id}
67+
<SimpleFileIcon
68+
width="32px"
69+
height="32px"
70+
aria-hidden="true"
71+
data-testid="doc-simple-icon"
72+
color={colorsTokens['primary-500']}
7973
/>
8074
)}
8175
</Box>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './DocIcon';
12
export * from './DocPage403';
23
export * from './ModalRemoveDoc';
34
export * from './SimpleDocItem';

0 commit comments

Comments
 (0)