Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4b50416
Add agents workflows banner and related translations
NicolasBonet May 20, 2026
7547cee
Add agents rules promo banner and related translations
NicolasBonet May 20, 2026
b8bf0f8
Update translations for agents promo banners across multiple languages
NicolasBonet May 20, 2026
9788cb2
Refactor agents promo banner rendering in Workspace Workflows page
NicolasBonet May 21, 2026
fa4e054
Add AgentPromotionalBanner component and integrate into PolicyRulesPa…
NicolasBonet May 21, 2026
7120f34
Update badgeHigher style for web compatibility
NicolasBonet May 21, 2026
479e99a
Refactor AgentPromotionalBanner badge implementation and update styles
NicolasBonet May 21, 2026
fd5b2c0
Refactor AgentPromotionalBanner to utilize BillingBanner component
NicolasBonet May 21, 2026
a842f1d
Refactor badge rendering in AgentPromotionalBanner for improved reada…
NicolasBonet May 21, 2026
cbb150a
Refactor AgentPromotionalBanner styles and badge alignment
NicolasBonet May 21, 2026
1ffca0a
Refactor AgentPromotionalBanner to remove unused styles and improve l…
NicolasBonet May 22, 2026
751d29d
Refactor BillingBanner component to remove unused rightIconFill prop
NicolasBonet May 22, 2026
f17a947
Merge branch 'main' into feat/91243-add-agent-promotion-banners-to-wo…
NicolasBonet May 25, 2026
5fdafee
Update AgentsPromoBannersTest to match on subtitles instead of titles…
NicolasBonet May 25, 2026
bdebb27
Merge branch 'main' into feat/91243-add-agent-promotion-banners-to-wo…
NicolasBonet May 25, 2026
aa3fb60
Add agent promotional banners to workspace
NicolasBonet May 25, 2026
0493fdc
Update AgentPromotionalBanner styles and layout
NicolasBonet May 25, 2026
b9df7b2
Update button size in AgentPromotionalBanner component
NicolasBonet May 25, 2026
df42ab3
Merge branch 'main' into feat/91243-add-agent-promotion-banners-to-wo…
NicolasBonet May 26, 2026
d7bb167
feat: fix spacing in mobile
NicolasBonet May 26, 2026
75575dd
fix: adjust badge alignment for web platform in promotional banner
NicolasBonet May 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9016,6 +9016,8 @@ const CONST = {
HAS_FILTER_NEGATION: 'hasFilterNegation',
},
CHANGE_POLICY_TRAINING_MODAL: 'changePolicyModal',
AGENTS_WORKFLOWS_BANNER: 'agentsWorkflowsBanner',
AGENTS_RULES_BANNER: 'agentsRulesBanner',
SMART_BANNER_HEIGHT: 152,

NAVIGATION_TESTS: {
Expand Down Expand Up @@ -9156,6 +9158,13 @@ const CONST = {
BILLING_BANNER: {
RIGHT_ICON: 'BillingBanner-RightIcon',
},
AGENTS_WORKFLOWS_BANNER: {
DISMISS: 'AgentsWorkflowsBanner-Dismiss',
},
AGENTS_RULES_BANNER: {
CTA: 'AgentsRulesBanner-CTA',
DISMISS: 'AgentsRulesBanner-Dismiss',
},
NAVIGATION_TAB_BAR: {
EXPENSIFY_LOGO: 'NavigationTabBar-ExpensifyLogo',
INBOX: 'NavigationTabBar-Inbox',
Expand Down
114 changes: 114 additions & 0 deletions src/components/AgentPromotionalBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React, {useMemo} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import {View} from 'react-native';
import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import BillingBanner from '@pages/settings/Subscription/CardSection/BillingBanner/BillingBanner';
import Badge from './Badge';
import Button from './Button';
import Text from './Text';

type AgentPromotionalBannerProps = {
/** Title shown next to the bot illustration. */
title: string;

/** Supporting copy under the title. */
subtitle: string;

/** Called when the dismiss (X) button is pressed. */
onDismiss: () => void;

/** Sentry label for the dismiss button. */
dismissSentryLabel: string;

/** Optional CTA text. When omitted, the CTA is not rendered. */
ctaText?: string;

/** Called when the CTA is pressed. Required when `ctaText` is set. */
onCtaPress?: () => void;

/** Sentry label for the CTA. Required when `ctaText` is set. */
ctaSentryLabel?: string;

/** Extra styles applied to the outer container. */
style?: StyleProp<ViewStyle>;
};

function AgentPromotionalBanner({title, subtitle, onDismiss, dismissSentryLabel, ctaText, onCtaPress, ctaSentryLabel, style}: AgentPromotionalBannerProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const illustrations = useMemoizedLazyIllustrations(['AiBot']);
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Close']);

const hasCta = !!ctaText && !!onCtaPress;

const titleNode = useMemo(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ CLEAN-REACT-PATTERNS-0 (docs)

React Compiler is enabled in this codebase and automatically memoizes derived values. The useMemo wrapping titleNode (line 48) and rightComponent (line 66) is redundant — the compiler will handle caching these JSX expressions based on their captured dependencies.

Remove both useMemo calls and declare the values as plain expressions:

const titleNode = (
    <View style={[styles.flexRow, styles.flexShrink1]}>
        <Text style={[styles.textStrong]}>
            {title}
            <Badge ... />
        </Text>
    </View>
);

Similarly for rightComponent — use a plain conditional expression instead of useMemo. Also remove the useMemo import from react (line 1).

Note: If this file does not compile with React Compiler, the manual memoization may be necessary until the compilation issue is resolved — verify with npm run react-compiler-compliance-check check-changed.


Reviewed at: 75575dd | Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.

() => (
<View style={[styles.flexRow, styles.flexShrink1]}>
<Text style={[styles.textStrong]}>
{title}
<Badge
badgeStyles={styles.agentPromotionalBannerBadge}
success
isStrong
isCondensed
text={translate('common.new')}
/>
</Text>
</View>
),
[title, styles, translate],
);

const rightComponent = useMemo(() => {
if (!hasCta) {
return null;
}
if (shouldUseNarrowLayout) {
return (
<View style={[styles.flex0, styles.flexBasis100, styles.maxWidth100Percentage, styles.justifyContentCenter]}>
<Button
success
medium
text={ctaText}
onPress={onCtaPress}
sentryLabel={ctaSentryLabel}
/>
</View>
);
}
return (
<Button
success
small
text={ctaText}
onPress={onCtaPress}
sentryLabel={ctaSentryLabel}
/>
);
}, [hasCta, shouldUseNarrowLayout, ctaText, onCtaPress, ctaSentryLabel, styles]);

return (
<View style={style}>
<BillingBanner
Comment thread
NicolasBonet marked this conversation as resolved.
icon={illustrations.AiBot}
title={titleNode}
subtitle={subtitle}
subtitleStyle={[styles.mt1]}
style={[styles.borderRadiusComponentLarge, styles.gap4]}
rightIcon={expensifyIcons.Close}
onRightIconPress={onDismiss}
rightIconAccessibilityLabel={translate('common.dismiss')}
rightIconSentryLabel={dismissSentryLabel}
rightComponent={rightComponent}
/>
</View>
);
}

AgentPromotionalBanner.displayName = 'AgentPromotionalBanner';

export default AgentPromotionalBanner;
7 changes: 7 additions & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2578,6 +2578,8 @@ ${amount} für ${merchant} – ${date}`,
addApprovalTip: 'Dieser Standard-Workflow gilt für alle Mitglieder, sofern kein spezifischerer Workflow vorhanden ist.',
approver: 'Genehmiger',
addApprovalsDescription: 'Zusätzliche Genehmigung einholen, bevor eine Zahlung autorisiert wird.',
automateApprovalsWithAgentsTitle: 'Genehmigungen mit Agenten automatisieren',
automateApprovalsWithAgentsSubtitle: 'Fügen Sie die untenstehende Person zum Workflow hinzu, um Genehmigungen zu automatisieren.',
makeOrTrackPaymentsTitle: 'Zahlungen',
makeOrTrackPaymentsDescription:
'Fügen Sie eine bevollmächtigte zahlende Person für in Expensify getätigte Zahlungen hinzu oder verfolgen Sie Zahlungen, die andernorts getätigt wurden.',
Expand Down Expand Up @@ -6987,6 +6989,11 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
`Gehe zu [weitere Funktionen](${moreFeaturesLink}) und aktiviere ${featureName}, um diese Funktion freizuschalten.`,
},
agentsPromoBanner: {
title: 'Sie sehen die benötigte Regel nicht? Fügen Sie eine:n Agent:in hinzu',
subtitle: 'Fügen Sie komplexe Regeln hinzu und reduzieren Sie manuelle Genehmigungen mit benutzerdefinierten Agenten.',
cta: 'Ausprobieren',
},
merchantRules: {
title: 'Händler',
subtitle: 'Legen Sie Händlerregeln fest, damit Spesen korrekt codiert ankommen und weniger Nachbearbeitung erfordern.',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2634,6 +2634,8 @@ const translations = {
addApprovalTip: 'This default workflow applies to all members, unless a more specific workflow exists.',
approver: 'Approver',
addApprovalsDescription: 'Require additional approval before authorizing a payment.',
automateApprovalsWithAgentsTitle: 'Automate approvals with agents',
automateApprovalsWithAgentsSubtitle: 'Add agent below to workflow to automate approvals.',
configureViaHR: ({provider}: {provider: string}) => `Configure via ${provider}.`,
hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
`Approvals are managed by your ${provider} integration. To update your approval workflow, head to your ${provider} connection settings.`,
Expand Down Expand Up @@ -7065,6 +7067,11 @@ const translations = {
unlockFeatureEnableWorkflowsSubtitle: (featureName: string) => `Add ${featureName} to unlock this feature.`,
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) => `Go to [more features](${moreFeaturesLink}) and enable ${featureName} to unlock this feature.`,
},
agentsPromoBanner: {
title: 'Don’t see the rule you need? Add an agent',
subtitle: 'Add complex rules and reduce manual approvals with custom agents.',
cta: 'Try it out',
},
merchantRules: {
title: 'Merchant',
subtitle: 'Set merchant rules so expenses arrive correctly coded and require less cleanup.',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2451,6 +2451,8 @@ ${amount} para ${merchant} - ${date}`,
addApprovalTip: 'Este flujo de trabajo por defecto se aplica a todos los miembros, a menos que exista un flujo de trabajo más específico.',
approver: 'Aprobador',
addApprovalsDescription: 'Requiere una aprobación adicional antes de autorizar un pago.',
automateApprovalsWithAgentsTitle: 'Automatiza las aprobaciones con agentes',
automateApprovalsWithAgentsSubtitle: 'Añade el agente de abajo al flujo de trabajo para automatizar las aprobaciones.',
configureViaHR: ({provider}: {provider: string}) => `Configurar mediante ${provider}.`,
hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
`Las aprobaciones se gestionan mediante tu integración de ${provider}. Para actualizar tu flujo de aprobación, ve a la configuración de conexión de ${provider}.`,
Expand Down Expand Up @@ -6905,6 +6907,11 @@ ${amount} para ${merchant} - ${date}`,
unlockFeatureEnableWorkflowsSubtitle: (featureName) => `Añade ${featureName} para desbloquear esta función.`,
enableFeatureSubtitle: (featureName, moreFeaturesLink) => `Ir a [más características](${moreFeaturesLink}) y habilita ${featureName} para desbloquear esta función.`,
},
agentsPromoBanner: {
title: '¿No ves la regla que necesitas? Añade un agente',
subtitle: 'Añade reglas complejas y reduce las aprobaciones manuales con agentes personalizados.',
cta: 'Pruébalo',
},
merchantRules: {
title: 'Comerciante',
subtitle: 'Configura las reglas de comerciante para que los gastos lleguen correctamente codificados y requieran menos limpieza.',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2586,6 +2586,8 @@ ${amount} pour ${merchant} - ${date}`,
addApprovalTip: 'Ce workflow par défaut s’applique à tous les membres, sauf si un workflow plus spécifique existe.',
approver: 'Approbateur',
addApprovalsDescription: 'Exiger une approbation supplémentaire avant d’autoriser un paiement.',
automateApprovalsWithAgentsTitle: 'Automatisez les approbations avec des agents',
automateApprovalsWithAgentsSubtitle: 'Ajoutez l’agent ci-dessous au flux de travail pour automatiser les approbations.',
makeOrTrackPaymentsTitle: 'Paiements',
makeOrTrackPaymentsDescription: 'Ajoutez un payeur autorisé pour les paiements effectués dans Expensify ou suivez les paiements effectués ailleurs.',
customApprovalWorkflowEnabled:
Expand Down Expand Up @@ -7011,6 +7013,11 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
`Allez dans [plus de fonctionnalités](${moreFeaturesLink}) et activez ${featureName} pour déverrouiller cette fonctionnalité.`,
},
agentsPromoBanner: {
title: 'Vous ne voyez pas la règle dont vous avez besoin ? Ajoutez un agent',
subtitle: 'Ajoutez des règles complexes et réduisez les approbations manuelles grâce à des agents personnalisés.',
cta: 'Essayer',
},
merchantRules: {
title: 'Commerçant',
subtitle: 'Définissez les règles de commerçant pour que les dépenses arrivent correctement codées et nécessitent moins de nettoyage.',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2574,6 +2574,8 @@ ${amount} per ${merchant} - ${date}`,
addApprovalTip: 'Questo flusso di lavoro predefinito si applica a tutti i membri, a meno che non esista un flusso di lavoro più specifico.',
approver: 'Approvante',
addApprovalsDescription: 'Richiedi un’approvazione aggiuntiva prima di autorizzare un pagamento.',
automateApprovalsWithAgentsTitle: 'Automatizza le approvazioni con gli agenti',
automateApprovalsWithAgentsSubtitle: 'Aggiungi l’agente qui sotto al workflow per automatizzare le approvazioni.',
makeOrTrackPaymentsTitle: 'Pagamenti',
makeOrTrackPaymentsDescription: 'Aggiungi un pagatore autorizzato per i pagamenti effettuati in Expensify o tieni traccia dei pagamenti effettuati altrove.',
customApprovalWorkflowEnabled:
Expand Down Expand Up @@ -6973,6 +6975,11 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
`Vai su [altre funzionalità](${moreFeaturesLink}) e abilita ${featureName} per sbloccare questa funzione.`,
},
agentsPromoBanner: {
title: 'Non vedi la regola che ti serve? Aggiungi un agente',
subtitle: 'Aggiungi regole complesse e riduci le approvazioni manuali con agenti personalizzati.',
cta: 'Prova ora',
},
merchantRules: {
title: 'Esercente',
subtitle: 'Imposta le regole per l’esercente in modo che le spese arrivino già codificate correttamente e richiedano meno correzioni.',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2549,6 +2549,8 @@ ${date} の ${merchant} への ${amount}`,
addApprovalTip: 'より詳細なワークフローが存在する場合を除き、このデフォルトのワークフローがすべてのメンバーに適用されます。',
approver: '承認者',
addApprovalsDescription: '支払いを承認する前に、追加の承認を必須にする。',
automateApprovalsWithAgentsTitle: '代理を使って承認を自動化する',
automateApprovalsWithAgentsSubtitle: '承認を自動化するには、以下のエージェントをワークフローに追加してください。',
makeOrTrackPaymentsTitle: '支払',
makeOrTrackPaymentsDescription: 'Expensifyでの支払いに対する承認済み支払者を追加するか、他の場所で行われた支払いを記録します。',
customApprovalWorkflowEnabled:
Expand Down Expand Up @@ -6895,6 +6897,11 @@ ${reportName}
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
`[その他の機能](${moreFeaturesLink})に移動し、${featureName} を有効にしてこの機能を利用できるようにしてください。`,
},
agentsPromoBanner: {
title: '必要なルールが見つかりませんか?エージェントを追加してください',
subtitle: '複雑なルールを追加し、カスタムエージェントで手動承認を減らしましょう。',
cta: 'お試しください',
},
merchantRules: {
title: '加盟店',
subtitle: '経費が正しくコード化され、後処理が最小限で済むように、取引先ルールを設定しましょう。',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2571,6 +2571,8 @@ ${amount} voor ${merchant} - ${date}`,
addApprovalTip: 'Deze standaardworkflow is van toepassing op alle leden, tenzij er een specifiekere workflow bestaat.',
approver: 'Fiatteur',
addApprovalsDescription: 'Extra goedkeuring vereisen voordat je een betaling autoriseert.',
automateApprovalsWithAgentsTitle: 'Automatiseer goedkeuringen met agents',
automateApprovalsWithAgentsSubtitle: 'Voeg hieronder een agent toe aan de workflow om goedkeuringen te automatiseren.',
makeOrTrackPaymentsTitle: 'Betalingen',
makeOrTrackPaymentsDescription: 'Voeg een gemachtigde betaler toe voor betalingen die in Expensify worden gedaan of volg betalingen die elders zijn gedaan.',
customApprovalWorkflowEnabled:
Expand Down Expand Up @@ -6950,6 +6952,11 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
`Ga naar [meer functies](${moreFeaturesLink}) en schakel ${featureName} in om deze functie te ontgrendelen.`,
},
agentsPromoBanner: {
title: 'Zie je de regel die je nodig hebt niet? Voeg een agent toe',
subtitle: 'Voeg complexe regels toe en verminder handmatige goedkeuringen met aangepaste agents.',
cta: 'Probeer het uit',
},
merchantRules: {
title: 'Handelaar',
subtitle: 'Stel de leveranciersregels in zodat onkosten correct gecodeerd binnenkomen en er minder nabewerking nodig is.',
Expand Down
3 changes: 3 additions & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2567,6 +2567,8 @@ ${amount} dla ${merchant} - ${date}`,
addApprovalTip: 'Domyślny proces pracy ma zastosowanie do wszystkich członków, chyba że istnieje bardziej szczegółowy proces pracy.',
approver: 'Osoba zatwierdzająca',
addApprovalsDescription: 'Wymagaj dodatkowej akceptacji przed autoryzacją płatności.',
automateApprovalsWithAgentsTitle: 'Automatyzuj zatwierdzanie z agentami',
automateApprovalsWithAgentsSubtitle: 'Dodaj agenta poniżej do przepływu pracy, aby zautomatyzować zatwierdzanie.',
makeOrTrackPaymentsTitle: 'Płatności',
makeOrTrackPaymentsDescription: 'Dodaj upoważnionego płatnika dla płatności dokonywanych w Expensify lub śledź płatności wykonywane gdzie indziej.',
customApprovalWorkflowEnabled:
Expand Down Expand Up @@ -6944,6 +6946,7 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
`Przejdź do [więcej funkcji](${moreFeaturesLink}) i włącz ${featureName}, aby odblokować tę funkcję.`,
},
agentsPromoBanner: {title: 'Nie widzisz potrzebnej reguły? Dodaj agenta', subtitle: 'Dodaj złożone reguły i ogranicz ręczne akceptacje dzięki własnym agentom.', cta: 'Wypróbuj'},
merchantRules: {
title: 'Sprzedawca',
subtitle: 'Skonfiguruj reguły dla sprzedawców, aby wydatki trafiały z prawidłowym kodowaniem i wymagały mniej poprawek.',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2565,6 +2565,8 @@ ${amount} para ${merchant} - ${date}`,
addApprovalTip: 'Este fluxo de trabalho padrão se aplica a todos os membros, a menos que exista um fluxo de trabalho mais específico.',
approver: 'Aprovador',
addApprovalsDescription: 'Exigir aprovação adicional antes de autorizar um pagamento.',
automateApprovalsWithAgentsTitle: 'Automatize aprovações com agentes',
automateApprovalsWithAgentsSubtitle: 'Adicione o agente abaixo ao fluxo de trabalho para automatizar as aprovações.',
makeOrTrackPaymentsTitle: 'Pagamentos',
makeOrTrackPaymentsDescription: 'Adicione um pagador autorizado para pagamentos feitos no Expensify ou acompanhe pagamentos feitos em outros lugares.',
customApprovalWorkflowEnabled:
Expand Down Expand Up @@ -6949,6 +6951,11 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
`Vá para [mais recursos](${moreFeaturesLink}) e ative ${featureName} para desbloquear este recurso.`,
},
agentsPromoBanner: {
title: 'Não encontrou a regra que precisa? Adicione um agente',
subtitle: 'Adicione regras complexas e reduza aprovações manuais com agentes personalizados.',
cta: 'Experimente',
},
merchantRules: {
title: 'Estabelecimento',
subtitle: 'Defina as regras de estabelecimento para que as despesas cheguem corretamente classificadas e exijam menos retrabalho.',
Expand Down
Loading
Loading