diff --git a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx
index 9e3f00124f84c..40207e0e3894d 100755
--- a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx
+++ b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx
@@ -186,6 +186,10 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
tagName: 'bullet-item',
contentModel: HTMLContentModel.block,
}),
+ 'sparkles-icon': HTMLElementModel.fromCustomModel({
+ tagName: 'sparkles-icon',
+ contentModel: HTMLContentModel.mixed,
+ }),
}),
[
styles.taskTitleMenuItem,
diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/SparklesIconRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/SparklesIconRenderer.tsx
new file mode 100644
index 0000000000000..b8c22956809df
--- /dev/null
+++ b/src/components/HTMLEngineProvider/HTMLRenderers/SparklesIconRenderer.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import {View} from 'react-native';
+import Icon from '@components/Icon';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import variables from '@styles/variables';
+
+/**
+ * Renders a Sparkles SVG icon as an inline custom HTML element
+ */
+function SparklesIconRenderer() {
+ const icons = useMemoizedLazyExpensifyIcons(['Sparkles']);
+ const theme = useTheme();
+ const styles = useThemeStyles();
+
+ return (
+
+
+
+ );
+}
+
+export default SparklesIconRenderer;
diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/index.ts b/src/components/HTMLEngineProvider/HTMLRenderers/index.ts
index f77dc115c8545..3d91670c38e75 100644
--- a/src/components/HTMLEngineProvider/HTMLRenderers/index.ts
+++ b/src/components/HTMLEngineProvider/HTMLRenderers/index.ts
@@ -16,6 +16,7 @@ import NextStepEmailRenderer from './NextStepEmailRenderer';
import PreRenderer from './PreRenderer';
import RBRRenderer from './RBRRenderer';
import ShortMentionRenderer from './ShortMentionRenderer';
+import SparklesIconRenderer from './SparklesIconRenderer';
import TaskTitleRenderer from './TaskTitleRenderer';
import TransactionHistoryLinkRenderer from './TransactionHistoryLinkRenderer';
import UserDetailsRenderer from './UserDetailsRenderer';
@@ -50,6 +51,7 @@ const HTMLEngineProviderComponentList: CustomTagRendererRecord = {
'concierge-link': ConciergeLinkRenderer,
'transaction-history-link': TransactionHistoryLinkRenderer,
'account-manager-link': AccountManagerLinkRenderer,
+ 'sparkles-icon': SparklesIconRenderer,
/* eslint-enable @typescript-eslint/naming-convention */
};
diff --git a/src/components/RenderHTML.tsx b/src/components/RenderHTML.tsx
index a52ccf2c8d969..ababd16463b8e 100644
--- a/src/components/RenderHTML.tsx
+++ b/src/components/RenderHTML.tsx
@@ -5,6 +5,7 @@ import useHasTextAncestor from '@hooks/useHasTextAncestor';
import useWindowDimensions from '@hooks/useWindowDimensions';
import Parser from '@libs/Parser';
import BulletItemRenderer from './HTMLEngineProvider/HTMLRenderers/BulletItemRenderer';
+import SparklesIconRenderer from './HTMLEngineProvider/HTMLRenderers/SparklesIconRenderer';
type LinkPressHandler = NonNullable['onPress'];
@@ -53,6 +54,7 @@ function RenderHTML({html: htmlParam, onLinkPress, isSelectable}: RenderHTMLProp
const renderers = {
/* eslint-disable @typescript-eslint/naming-convention */
'bullet-item': BulletItemRenderer,
+ 'sparkles-icon': SparklesIconRenderer,
};
const htmlSource = (
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 8a6be1581b8f4..60edcacd58d4d 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1586,7 +1586,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: 'Der Gesamtbetrag ist zu hoch. Verringere die Stunden oder reduziere den Satz.',
},
correctRateError: 'Beheben Sie den Kursfehler und versuchen Sie es erneut.',
- AskToExplain: `. Erklären ✨`,
+ AskToExplain: `. Erklären`,
duplicateNonDefaultWorkspacePerDiemError:
'Sie können Per-Diem-Ausgaben nicht über mehrere Workspaces hinweg duplizieren, da sich die Sätze zwischen den Workspaces unterscheiden können.',
rulesModifiedFields: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 3f10e590d6ed3..70e48407f64e9 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1611,7 +1611,7 @@ const translations = {
amountTooLargeError: 'The total amount is too large. Lower the hours or reduce the rate.',
},
correctRateError: 'Fix the rate error and try again.',
- AskToExplain: `. Explain ✨`,
+ AskToExplain: `. Explain`,
rulesModifiedFields: {
reimbursable: (value: boolean) => (value ? 'marked the expense as "reimbursable"' : 'marked the expense as "non-reimbursable"'),
billable: (value: boolean) => (value ? 'marked the expense as "billable"' : 'marked the expense as "non-billable"'),
diff --git a/src/languages/es.ts b/src/languages/es.ts
index b415f6a0dd7fa..414775e1f9854 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1452,7 +1452,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: 'El importe total es demasiado alto. Reduce las horas o disminuye la tasa.',
},
correctRateError: 'Corrige el error de la tasa y vuelve a intentarlo.',
- AskToExplain: `. Explicar ✨`,
+ AskToExplain: `. Explicar`,
rulesModifiedFields: {
reimbursable: (value: boolean) => (value ? 'marcó el gasto como "reembolsable"' : 'marcó el gasto como "no reembolsable"'),
billable: (value: boolean) => (value ? 'marcó el gasto como "facturable"' : 'marcó el gasto como "no facturable"'),
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 0b82ad790797b..746e79a43145f 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1591,7 +1591,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: 'Le montant total est trop élevé. Réduisez le nombre d’heures ou diminuez le taux.',
},
correctRateError: 'Corrigez l’erreur de taux et réessayez.',
- AskToExplain: `. Expliquer ✨`,
+ AskToExplain: `. Expliquer`,
duplicateNonDefaultWorkspacePerDiemError:
'Vous ne pouvez pas dupliquer les indemnités journalières entre plusieurs espaces de travail, car les taux peuvent différer d’un espace de travail à l’autre.',
rulesModifiedFields: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index d273792b023f0..89ed00830822c 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1583,7 +1583,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: 'L’importo totale è troppo alto. Riduci le ore o abbassa la tariffa.',
},
correctRateError: "Correggi l'errore di tariffa e riprova.",
- AskToExplain: `. Spiega ✨`,
+ AskToExplain: `. Spiega`,
duplicateNonDefaultWorkspacePerDiemError: 'Non puoi duplicare le spese di diaria tra diversi spazi di lavoro perché le tariffe potrebbero essere diverse tra gli spazi di lavoro.',
rulesModifiedFields: {
reimbursable: (value: boolean) => (value ? 'ha contrassegnato la spesa come "rimborsabile"' : 'ha contrassegnato la spesa come "non rimborsabile"'),
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 0a811ba9bb8c5..9cad80325ba19 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1573,7 +1573,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: '合計金額が大きすぎます。時間を減らすか、レートを下げてください。',
},
correctRateError: 'レートのエラーを修正して、もう一度お試しください。',
- AskToExplain: `・説明 ✨`,
+ AskToExplain: `・説明`,
duplicateNonDefaultWorkspacePerDiemError: 'ワークスペースごとに日当レートが異なる場合があるため、日当経費をワークスペース間で複製することはできません。',
rulesModifiedFields: {
reimbursable: (value: boolean) => (value ? '経費を「精算対象」に指定しました' : '経費を「精算対象外」にマークしました'),
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 6ffe1f3c1a213..975839fbd2149 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1581,7 +1581,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: 'Het totale bedrag is te hoog. Verlaag het aantal uren of verlaag het tarief.',
},
correctRateError: 'Los de tarieffout op en probeer het opnieuw.',
- AskToExplain: `. Uitleggen ✨`,
+ AskToExplain: `. Uitleggen`,
duplicateNonDefaultWorkspacePerDiemError: 'Je kunt dagvergoedingen niet dupliceren tussen werkruimtes, omdat de tarieven per werkruimte kunnen verschillen.',
rulesModifiedFields: {
reimbursable: (value: boolean) => (value ? 'markeerde de uitgave als „terugbetaalbaar”' : 'heeft de uitgave als ‘niet-vergoedbaar’ gemarkeerd'),
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 5fac6256ad35a..4356113bae61d 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1580,7 +1580,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: 'Łączna kwota jest zbyt wysoka. Zmniejsz liczbę godzin lub obniż stawkę.',
},
correctRateError: 'Napraw błąd stawki i spróbuj ponownie.',
- AskToExplain: `. Wyjaśnij ✨`,
+ AskToExplain: `. Wyjaśnij`,
duplicateNonDefaultWorkspacePerDiemError:
'Nie możesz duplikować wydatków z tytułu diet między przestrzeniami roboczymi, ponieważ stawki mogą się różnić między poszczególnymi przestrzeniami.',
rulesModifiedFields: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index a441fe5c534ce..250ae762ee5f9 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1578,7 +1578,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: 'O valor total é muito alto. Diminua as horas ou reduza a tarifa.',
},
correctRateError: 'Corrija o erro de taxa e tente novamente.',
- AskToExplain: `. Explicar ✨`,
+ AskToExplain: `. Explicar`,
duplicateNonDefaultWorkspacePerDiemError: 'Você não pode duplicar despesas de diárias entre espaços de trabalho porque as tarifas podem variar entre eles.',
rulesModifiedFields: {
reimbursable: (value: boolean) => (value ? 'marcou a despesa como "reembolsável"' : 'marcou a despesa como “não reembolsável”'),
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 3f3090d975a42..bba0974a58e33 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1548,7 +1548,7 @@ const translations: TranslationDeepObject = {
amountTooLargeError: '总金额过大。请减少工时或降低费率。',
},
correctRateError: '修复费率错误后请重试。',
- AskToExplain: `。说明 ✨`,
+ AskToExplain: `。说明`,
duplicateNonDefaultWorkspacePerDiemError: '您无法在不同工作区之间复制每日津贴报销,因为各工作区的补贴标准可能不同。',
rulesModifiedFields: {
reimbursable: (value: boolean) => (value ? '将该报销单标记为“可报销”' : '将该报销单标记为“不可报销”'),