Skip to content

Commit 2337175

Browse files
authored
feat(ui): DOMA-13025 add emoticons in rich text area (#7386)
* feat(ui): DOMA-13025 add emoji support in RichTextArea component * feat(ui): DOMA-13025 extend RichTextArea with emoji dropdown labels and default values * feat(ui): DOMA-13025 fix after review * feat(ui): DOMA-13025 enhance RichTextArea and TextArea components with emoji and copy functionality * feat(ui): DOMA-13025 migrate copy to ui kit copu option * feat(ui): DOMA-13025 implement copy button functionality across CommentForm, InputStepForm, BaseIncidentForm, and BaseTicketPropertyHintForm components * feat(ui): DOMA-13025 enhance CommentForm, InputStepForm, BaseIncidentForm, and BaseTicketPropertyHintForm with improved emoji support and tooltip labels * feat(ui): DOMA-13025 add TODO for locale support in RichTextArea and enhance style with squircle corner shape * feat(ui): DOMA-13025 fix stylelint
1 parent 575445e commit 2337175

File tree

13 files changed

+494
-25
lines changed

13 files changed

+494
-25
lines changed

apps/condo/domains/news/components/NewsForm/InputStep/InputStepForm.tsx

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useIntl } from '@open-condo/next/intl'
99
import {
1010
Button,
1111
Input,
12+
RichTextAreaProps,
1213
Tooltip,
1314
Typography,
1415
} from '@open-condo/ui'
@@ -91,6 +92,7 @@ const DefaultAiTextArea: React.FC<DefaultAiTextAreaProps> = ({
9192
const GenericErrorMessage = intl.formatMessage({ id: 'ServerErrorPleaseTryAgainLater' })
9293
const UndoTooltipText = intl.formatMessage({ id: 'richTextArea.toolbar.undo' })
9394
const RedoTooltipText = intl.formatMessage({ id: 'richTextArea.toolbar.redo' })
95+
const EmojiTooltipText = intl.formatMessage({ id: 'richTextArea.toolbar.emoji' })
9496
const BoldTooltipText = intl.formatMessage({ id: 'richTextArea.toolbar.bold' })
9597
const ItalicTooltipText = intl.formatMessage({ id: 'richTextArea.toolbar.italic' })
9698
const OrderedListTooltipText = intl.formatMessage({ id: 'richTextArea.toolbar.orderedList' })
@@ -100,6 +102,16 @@ const DefaultAiTextArea: React.FC<DefaultAiTextAreaProps> = ({
100102
const LinkModalUrlLabel = intl.formatMessage({ id: 'richTextArea.linkModal.urlLabel' })
101103
const LinkModalTextLabel = intl.formatMessage({ id: 'richTextArea.linkModal.textLabel' })
102104
const LinkModalSubmitLabel = intl.formatMessage({ id: 'richTextArea.linkModal.submitLabel' })
105+
const EmojiDropdownCategoriesActivity = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.activity' })
106+
const EmojiDropdownCategoriesFlags = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.flags' })
107+
const EmojiDropdownCategoriesFoods = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.foods' })
108+
const EmojiDropdownCategoriesFrequent = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.frequent' })
109+
const EmojiDropdownCategoriesNature = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.nature' })
110+
const EmojiDropdownCategoriesObjects = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.objects' })
111+
const EmojiDropdownCategoriesPeople = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.people' })
112+
const EmojiDropdownCategoriesPlaces = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.places' })
113+
const EmojiDropdownCategoriesSymbols = intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.symbols' })
114+
103115

104116
const toolbarLabels = useMemo(() => ({
105117
undo: UndoTooltipText,
@@ -112,12 +124,30 @@ const DefaultAiTextArea: React.FC<DefaultAiTextAreaProps> = ({
112124
removeFormatting: RemoveFormattingTooltipText,
113125
}), [LinkTooltipText, UnorderedListTooltipText, RemoveFormattingTooltipText, OrderedListTooltipText, BoldTooltipText, ItalicTooltipText, RedoTooltipText, UndoTooltipText])
114126

127+
const bottomPanelLabels = useMemo(() => ({
128+
emoji: EmojiTooltipText,
129+
}), [EmojiTooltipText])
130+
115131
const linkModalLabels = useMemo(() => ({
116132
urlLabel: LinkModalUrlLabel,
117133
textLabel: LinkModalTextLabel,
118134
submitLabel: LinkModalSubmitLabel,
119135
}), [LinkModalUrlLabel, LinkModalTextLabel, LinkModalSubmitLabel])
120136

137+
const emojiDropdownLabels = useMemo(() => ({
138+
categories: {
139+
activity: EmojiDropdownCategoriesActivity,
140+
flags: EmojiDropdownCategoriesFlags,
141+
foods: EmojiDropdownCategoriesFoods,
142+
frequent: EmojiDropdownCategoriesFrequent,
143+
nature: EmojiDropdownCategoriesNature,
144+
objects: EmojiDropdownCategoriesObjects,
145+
people: EmojiDropdownCategoriesPeople,
146+
places: EmojiDropdownCategoriesPlaces,
147+
symbols: EmojiDropdownCategoriesSymbols,
148+
},
149+
}), [EmojiDropdownCategoriesActivity, EmojiDropdownCategoriesFlags, EmojiDropdownCategoriesFoods, EmojiDropdownCategoriesFrequent, EmojiDropdownCategoriesNature, EmojiDropdownCategoriesObjects, EmojiDropdownCategoriesPeople, EmojiDropdownCategoriesPlaces, EmojiDropdownCategoriesSymbols])
150+
121151
const { status: validationStatus } = Form.Item.useStatus()
122152
const inputHasError = validationStatus === 'error'
123153

@@ -220,7 +250,7 @@ const DefaultAiTextArea: React.FC<DefaultAiTextAreaProps> = ({
220250
}
221251
}, [copied, useRichText, value])
222252

223-
const bottomPanelUtils = [
253+
const bottomPanelUtils: RichTextAreaProps['bottomPanelUtils'] = [
224254
<Tooltip
225255
title={copied ? CopiedTooltipText : CopyTooltipText }
226256
placement='top'
@@ -236,6 +266,7 @@ const DefaultAiTextArea: React.FC<DefaultAiTextAreaProps> = ({
236266
icon={copied ? (<CheckCircle size='small' />) : (<Copy size='small'/>) }
237267
/>
238268
</Tooltip>,
269+
'emoji',
239270
...(rewriteNewsTextEnabled ? [
240271
<Button
241272
key='improveButton'
@@ -274,7 +305,9 @@ const DefaultAiTextArea: React.FC<DefaultAiTextAreaProps> = ({
274305
disabled={isRewriteNewsTextLoading}
275306
customLabels={{
276307
toolbar: toolbarLabels,
308+
emojiDropdown: emojiDropdownLabels,
277309
linkModal: linkModalLabels,
310+
bottomPanelLabels: bottomPanelLabels,
278311
}}
279312
type='inline'
280313
bottomPanelUtils={bottomPanelUtils}
@@ -290,6 +323,9 @@ const DefaultAiTextArea: React.FC<DefaultAiTextAreaProps> = ({
290323
value={value}
291324
autoSize={{ minRows: 2, maxRows: 5 }}
292325
disabled={isRewriteNewsTextLoading}
326+
customLabels={{
327+
emojiDropdown: emojiDropdownLabels,
328+
}}
293329
bottomPanelUtils={bottomPanelUtils}
294330
/>
295331
)}

apps/condo/domains/ticket/components/TicketPropertyHint/BaseTicketPropertyHintForm.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,30 @@ export const BaseTicketPropertyHintForm: React.FC<BaseTicketPropertyHintFormProp
118118
removeFormatting: intl.formatMessage({ id: 'richTextArea.toolbar.removeFormatting' }),
119119
}), [intl])
120120

121+
const bottomPanelLabels = useMemo(() => ({
122+
emoji: intl.formatMessage({ id: 'richTextArea.toolbar.emoji' }),
123+
}), [intl])
124+
121125
const linkModalLabels = useMemo(() => ({
122126
urlLabel: intl.formatMessage({ id: 'richTextArea.linkModal.urlLabel' }),
123127
textLabel: intl.formatMessage({ id: 'richTextArea.linkModal.textLabel' }),
124128
submitLabel: intl.formatMessage({ id: 'richTextArea.linkModal.submitLabel' }),
125129
}), [intl])
126130

131+
const emojiDropdownLabels = useMemo(() => ({
132+
categories: {
133+
activity: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.activity' }),
134+
flags: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.flags' }),
135+
foods: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.foods' }),
136+
frequent: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.frequent' }),
137+
nature: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.nature' }),
138+
objects: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.objects' }),
139+
people: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.people' }),
140+
places: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.places' }),
141+
symbols: intl.formatMessage({ id: 'richTextArea.emojiDropdown.categories.symbols' }),
142+
},
143+
}), [intl])
144+
127145
const router = useRouter()
128146
const client = useApolloClient()
129147

@@ -304,9 +322,12 @@ export const BaseTicketPropertyHintForm: React.FC<BaseTicketPropertyHintFormProp
304322
placeholder={HintMessage}
305323
maxLength={5000}
306324
autoSize={{ minRows: 2 }}
325+
bottomPanelUtils={['emoji']}
307326
customLabels={{
308327
toolbar: toolbarLabels,
309328
linkModal: linkModalLabels,
329+
emojiDropdown: emojiDropdownLabels,
330+
bottomPanelLabels: bottomPanelLabels,
310331
}}
311332
/>
312333
</Col>

apps/condo/lang/en/en.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3832,12 +3832,22 @@
38323832
"richTextArea.toolbar.undo": "Undo",
38333833
"richTextArea.toolbar.redo": "Redo",
38343834
"richTextArea.toolbar.link": "Link",
3835+
"richTextArea.toolbar.emoji": "Emoji",
38353836
"richTextArea.toolbar.bold": "Bold",
38363837
"richTextArea.toolbar.italic": "Italic",
38373838
"richTextArea.toolbar.unorderedList": "Bulleted list",
38383839
"richTextArea.toolbar.orderedList": "Numbered list",
38393840
"richTextArea.toolbar.removeFormatting": "Remove formatting",
38403841
"richTextArea.linkModal.urlLabel": "Link",
38413842
"richTextArea.linkModal.textLabel": "Text",
3842-
"richTextArea.linkModal.submitLabel": "Ok"
3843+
"richTextArea.linkModal.submitLabel": "Ok",
3844+
"richTextArea.emojiDropdown.categories.activity": "Activity",
3845+
"richTextArea.emojiDropdown.categories.flags": "Flags",
3846+
"richTextArea.emojiDropdown.categories.foods": "Foods",
3847+
"richTextArea.emojiDropdown.categories.frequent": "Frequent",
3848+
"richTextArea.emojiDropdown.categories.nature": "Nature",
3849+
"richTextArea.emojiDropdown.categories.objects": "Objects",
3850+
"richTextArea.emojiDropdown.categories.people": "People",
3851+
"richTextArea.emojiDropdown.categories.places": "Places",
3852+
"richTextArea.emojiDropdown.categories.symbols": "Symbols"
38433853
}

apps/condo/lang/es/es.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3832,12 +3832,22 @@
38323832
"richTextArea.toolbar.undo": "Deshacer",
38333833
"richTextArea.toolbar.redo": "Rehacer",
38343834
"richTextArea.toolbar.link": "Enlace",
3835+
"richTextArea.toolbar.emoji": "Emoji",
38353836
"richTextArea.toolbar.bold": "Negrita",
38363837
"richTextArea.toolbar.italic": "Cursiva",
38373838
"richTextArea.toolbar.unorderedList": "Lista con viñetas",
38383839
"richTextArea.toolbar.orderedList": "Lista numerada",
38393840
"richTextArea.toolbar.removeFormatting": "Quitar formato",
38403841
"richTextArea.linkModal.urlLabel": "Enlace",
38413842
"richTextArea.linkModal.textLabel": "Texto",
3842-
"richTextArea.linkModal.submitLabel": "Ok"
3843+
"richTextArea.linkModal.submitLabel": "Ok",
3844+
"richTextArea.emojiDropdown.categories.activity": "Actividad",
3845+
"richTextArea.emojiDropdown.categories.flags": "Banderas",
3846+
"richTextArea.emojiDropdown.categories.foods": "Comida",
3847+
"richTextArea.emojiDropdown.categories.frequent": "Frecuentes",
3848+
"richTextArea.emojiDropdown.categories.nature": "Naturaleza",
3849+
"richTextArea.emojiDropdown.categories.objects": "Objetos",
3850+
"richTextArea.emojiDropdown.categories.people": "Personas",
3851+
"richTextArea.emojiDropdown.categories.places": "Lugares",
3852+
"richTextArea.emojiDropdown.categories.symbols": "Símbolos"
38433853
}

apps/condo/lang/ru/ru.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3832,12 +3832,22 @@
38323832
"richTextArea.toolbar.undo": "Шаг назад",
38333833
"richTextArea.toolbar.redo": "Шаг вперед",
38343834
"richTextArea.toolbar.link": "Вставить ссылку",
3835+
"richTextArea.toolbar.emoji": "Вставить смайлик",
38353836
"richTextArea.toolbar.bold": "Полужирный текст",
38363837
"richTextArea.toolbar.italic": "Курсивный текст",
38373838
"richTextArea.toolbar.unorderedList": "Маркированный список",
38383839
"richTextArea.toolbar.orderedList": "Нумерованный список",
38393840
"richTextArea.toolbar.removeFormatting": "Очистить форматирование",
38403841
"richTextArea.linkModal.urlLabel": "Ссылка",
38413842
"richTextArea.linkModal.textLabel": "Текст",
3842-
"richTextArea.linkModal.submitLabel": "Ок"
3843+
"richTextArea.linkModal.submitLabel": "Ок",
3844+
"richTextArea.emojiDropdown.categories.activity": "Активности",
3845+
"richTextArea.emojiDropdown.categories.flags": "Флаги",
3846+
"richTextArea.emojiDropdown.categories.foods": "Еда и напитки",
3847+
"richTextArea.emojiDropdown.categories.frequent": "Часто используемые",
3848+
"richTextArea.emojiDropdown.categories.nature": "Животные и природа",
3849+
"richTextArea.emojiDropdown.categories.objects": "Предметы",
3850+
"richTextArea.emojiDropdown.categories.people": "Эмоции и люди",
3851+
"richTextArea.emojiDropdown.categories.places": "Путешествия и места",
3852+
"richTextArea.emojiDropdown.categories.symbols": "Символы"
38433853
}

packages/ui/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@
127127
"@dnd-kit/core": "^6.3.1",
128128
"@dnd-kit/sortable": "^10.0.0",
129129
"@dnd-kit/utilities": "^3.2.2",
130+
"@emoji-mart/data": "^1.2.1",
131+
"@emoji-mart/react": "^1.1.1",
130132
"@open-condo/icons": "workspace:^",
131133
"@tanstack/react-table": "^8.1.6",
132134
"@tiptap/core": "^3.20.0",
@@ -147,6 +149,7 @@
147149
"@tiptap/starter-kit": "^3.20.0",
148150
"antd": "^4.24.12",
149151
"classnames": "^2.5.1",
152+
"emoji-mart": "^5.6.0",
150153
"react-markdown": "^6",
151154
"react-phone-input-2": "^2.15.1",
152155
"remark-gfm": "^1",

0 commit comments

Comments
 (0)