diff --git a/projects/js-packages/components/changelog/change-migrate-cut-wp-ui b/projects/js-packages/components/changelog/change-migrate-cut-wp-ui
new file mode 100644
index 000000000000..ec760138cee1
--- /dev/null
+++ b/projects/js-packages/components/changelog/change-migrate-cut-wp-ui
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+
+Mark ContextualUpgradeTrigger as @deprecated. Use Notice from @wordpress/ui instead. The implementation is unchanged.
diff --git a/projects/js-packages/components/components/contextual-upgrade-trigger/index.tsx b/projects/js-packages/components/components/contextual-upgrade-trigger/index.tsx
index 2c43bd797ed2..ecd0f75f1ba9 100644
--- a/projects/js-packages/components/components/contextual-upgrade-trigger/index.tsx
+++ b/projects/js-packages/components/components/contextual-upgrade-trigger/index.tsx
@@ -6,6 +6,21 @@ import styles from './style.module.scss';
import { CutBaseProps } from './types.ts';
import type { FC } from 'react';
+/**
+ * ContextualUpgradeTrigger component.
+ *
+ * @deprecated Use `Notice` from `@wordpress/ui` instead. Compose with `Notice.Root` (`intent="info"`), `Notice.Description` for the body, and `Notice.Actions` + `Notice.ActionLink` / `Notice.ActionButton` for the CTA. See https://github.com/Automattic/jetpack/issues/48160 for migration guidance.
+ *
+ * @param props - The component properties.
+ * @param props.description - The body copy describing the upgrade context.
+ * @param props.cta - The CTA label.
+ * @param props.onClick - Click handler when rendered as a button.
+ * @param props.href - When provided, renders as an anchor instead of a button.
+ * @param props.openInNewTab - Whether to open the link in a new tab.
+ * @param props.className - Optional class for the root element.
+ * @param props.tooltipText - Optional tooltip body shown next to the description.
+ * @return The rendered upgrade trigger.
+ */
const ContextualUpgradeTrigger: FC< CutBaseProps > = ( {
description,
cta,
diff --git a/projects/js-packages/scan/changelog/change-migrate-cut-wp-ui b/projects/js-packages/scan/changelog/change-migrate-cut-wp-ui
new file mode 100644
index 000000000000..b25b23aae75c
--- /dev/null
+++ b/projects/js-packages/scan/changelog/change-migrate-cut-wp-ui
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+
+Replace internal ContextualUpgradeTrigger upgrade prompts with @wordpress/ui Notice composition. Internal refactor with a Notice-style visual refresh.
diff --git a/projects/js-packages/scan/src/components/threat-modal/threat-fix-details.tsx b/projects/js-packages/scan/src/components/threat-modal/threat-fix-details.tsx
index eb5a2b00d9ef..466f6490bad3 100644
--- a/projects/js-packages/scan/src/components/threat-modal/threat-fix-details.tsx
+++ b/projects/js-packages/scan/src/components/threat-modal/threat-fix-details.tsx
@@ -1,5 +1,6 @@
-import { ContextualUpgradeTrigger, Text } from '@automattic/jetpack-components';
+import { Text } from '@automattic/jetpack-components';
import { __, sprintf } from '@wordpress/i18n';
+import { Notice } from '@wordpress/ui';
import { useMemo, useContext } from 'react';
import { getFixerDescription } from '@automattic/jetpack-scan';
import { ThreatModalContext } from './index.tsx';
@@ -48,14 +49,16 @@ const ThreatFixDetails = (): JSX.Element => {
{ title }
{ fix }
{ handleUpgradeClick && (
-
+
+
+ { __( 'Looking for advanced scan results and one-click fixes?', 'jetpack-scan' ) }
+
+
+
+ { __( 'Upgrade Jetpack now', 'jetpack-scan' ) }
+
+
+
) }
);
diff --git a/projects/packages/publicize/_inc/components/admin-page/test/social-module-toggle.test.jsx b/projects/packages/publicize/_inc/components/admin-page/test/social-module-toggle.test.jsx
index e1a065361d64..2f10b52ecfa3 100644
--- a/projects/packages/publicize/_inc/components/admin-page/test/social-module-toggle.test.jsx
+++ b/projects/packages/publicize/_inc/components/admin-page/test/social-module-toggle.test.jsx
@@ -16,6 +16,11 @@ describe( 'SocialModuleToggle', () => {
clearMockedScriptData();
} );
+ // @wordpress/ui Notice triggers @wordpress/a11y speak() which renders the
+ // same description text into a visually-hidden .a11y-speak-region. Exclude
+ // that region from text queries so the assertions target the visible Notice.
+ const ignoreA11ySpeak = { ignore: 'script, style, .a11y-speak-region' };
+
it( 'should render connection management component by default', () => {
render( );
@@ -25,7 +30,9 @@ describe( 'SocialModuleToggle', () => {
it( 'should show upgrade trigger when no paid features', () => {
render( );
- expect( screen.getByText( /Unlock advanced sharing options/i ) ).toBeInTheDocument();
+ expect(
+ screen.getByText( /Unlock advanced sharing options/i, ignoreA11ySpeak )
+ ).toBeInTheDocument();
} );
it( 'should not show upgrade trigger with paid features', () => {
@@ -40,6 +47,8 @@ describe( 'SocialModuleToggle', () => {
} );
render( );
- expect( screen.queryByText( /Unlock advanced sharing options/i ) ).not.toBeInTheDocument();
+ expect(
+ screen.queryByText( /Unlock advanced sharing options/i, ignoreA11ySpeak )
+ ).not.toBeInTheDocument();
} );
} );
diff --git a/projects/packages/publicize/_inc/components/admin-page/toggles/social-module-toggle/index.tsx b/projects/packages/publicize/_inc/components/admin-page/toggles/social-module-toggle/index.tsx
index 186e89b5e69e..e5d1aa3cca0b 100644
--- a/projects/packages/publicize/_inc/components/admin-page/toggles/social-module-toggle/index.tsx
+++ b/projects/packages/publicize/_inc/components/admin-page/toggles/social-module-toggle/index.tsx
@@ -1,5 +1,5 @@
import {
- ContextualUpgradeTrigger,
+ IconTooltip,
Text,
getRedirectUrl,
useBreakpointMatch,
@@ -7,7 +7,7 @@ import {
import { getScriptData, isWpcomPlatformSite } from '@automattic/jetpack-script-data';
import { useSelect, useDispatch } from '@wordpress/data';
import { __, _x } from '@wordpress/i18n';
-import { Link } from '@wordpress/ui';
+import { Link, Notice } from '@wordpress/ui';
import clsx from 'clsx';
import { useCallback } from 'react';
import { store as socialStore } from '../../../../social-store';
@@ -93,19 +93,29 @@ const SocialModuleToggle: FC = () => {
{ ! isWpcomPlatformSite() && ! hasSocialPaidFeatures() ? (
-
+
+
+ { __( 'Unlock advanced sharing options', 'jetpack-publicize-pkg' ) }{ ' ' }
+
+
+ { __(
+ 'Share custom images and videos that capture attention, use our powerful Social Image Generator to create stunning visuals, and access priority support for expert help whenever you need it.',
+ 'jetpack-publicize-pkg'
+ ) }
+
+
+
+
+
+ { __( 'Power up Jetpack Social', 'jetpack-publicize-pkg' ) }
+
+
+
) : null }
{ isModuleEnabled && }
{ renderConnectionManagement() }
diff --git a/projects/packages/publicize/_inc/components/admin-page/toggles/social-module-toggle/styles.module.scss b/projects/packages/publicize/_inc/components/admin-page/toggles/social-module-toggle/styles.module.scss
index 39ab329a136b..38a2437035f5 100644
--- a/projects/packages/publicize/_inc/components/admin-page/toggles/social-module-toggle/styles.module.scss
+++ b/projects/packages/publicize/_inc/components/admin-page/toggles/social-module-toggle/styles.module.scss
@@ -44,3 +44,4 @@
.learn {
text-wrap: nowrap;
}
+
diff --git a/projects/packages/publicize/changelog/change-migrate-cut-wp-ui b/projects/packages/publicize/changelog/change-migrate-cut-wp-ui
new file mode 100644
index 000000000000..b25b23aae75c
--- /dev/null
+++ b/projects/packages/publicize/changelog/change-migrate-cut-wp-ui
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+
+Replace internal ContextualUpgradeTrigger upgrade prompts with @wordpress/ui Notice composition. Internal refactor with a Notice-style visual refresh.
diff --git a/projects/packages/search/changelog/change-migrate-cut-wp-ui b/projects/packages/search/changelog/change-migrate-cut-wp-ui
new file mode 100644
index 000000000000..b25b23aae75c
--- /dev/null
+++ b/projects/packages/search/changelog/change-migrate-cut-wp-ui
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+
+Replace internal ContextualUpgradeTrigger upgrade prompts with @wordpress/ui Notice composition. Internal refactor with a Notice-style visual refresh.
diff --git a/projects/packages/search/src/dashboard/components/pages/sections/plan-usage-section.jsx b/projects/packages/search/src/dashboard/components/pages/sections/plan-usage-section.jsx
index 51ea85ecedb3..149081c6843e 100644
--- a/projects/packages/search/src/dashboard/components/pages/sections/plan-usage-section.jsx
+++ b/projects/packages/search/src/dashboard/components/pages/sections/plan-usage-section.jsx
@@ -1,7 +1,6 @@
-import { ContextualUpgradeTrigger, ThemeProvider } from '@automattic/jetpack-components';
import { createInterpolateElement } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
-import { Link } from '@wordpress/ui';
+import { Link, Notice } from '@wordpress/ui';
import { useState, useCallback, useMemo } from 'react';
import DonutMeterContainer, { formatNumber } from '../../donut-meter-container';
import PlanSummary from './plan-summary';
@@ -300,17 +299,17 @@ const getUpgradeMessages = () => {
};
const UpgradeTrigger = ( { upgradeMessage, ctaCallback } ) => {
- // const upgradeMessage = type && getUpgradeMessages()[ type ];
- const triggerData = upgradeMessage && { ...upgradeMessage, onClick: ctaCallback };
+ if ( ! upgradeMessage ) {
+ return null;
+ }
return (
- <>
- { triggerData && (
-
-
-
- ) }
- >
+
+ { upgradeMessage.description }
+
+ { upgradeMessage.cta }
+
+
);
};
diff --git a/projects/packages/search/src/dashboard/components/pages/sections/test/plan-usage-section.test.jsx b/projects/packages/search/src/dashboard/components/pages/sections/test/plan-usage-section.test.jsx
index 6bfc782d8f10..66f887120bdc 100644
--- a/projects/packages/search/src/dashboard/components/pages/sections/test/plan-usage-section.test.jsx
+++ b/projects/packages/search/src/dashboard/components/pages/sections/test/plan-usage-section.test.jsx
@@ -1,18 +1,18 @@
import { render, screen } from '@testing-library/react';
import PlanUsageSection from '../plan-usage-section';
-jest.mock( '@automattic/jetpack-components', () => ( {
- ContextualUpgradeTrigger: ( { description, cta } ) => (
-
- { description }
- { cta }
-
- ),
- ThemeProvider: ( { children } ) => <>{ children }>,
-} ) );
-
jest.mock( '@wordpress/ui', () => ( {
Link: ( { children, href } ) => { children },
+ Notice: {
+ Root: ( { children } ) => { children }
,
+ Description: ( { children } ) => { children },
+ Actions: ( { children } ) => { children }
,
+ ActionButton: ( { children, onClick } ) => (
+
+ ),
+ },
} ) );
jest.mock( '../../../donut-meter-container', () => {
diff --git a/projects/packages/search/tests/js/dashboard/pages/dashboard-page.test.jsx b/projects/packages/search/tests/js/dashboard/pages/dashboard-page.test.jsx
index 2007a5cf78f0..e5b983735cd7 100644
--- a/projects/packages/search/tests/js/dashboard/pages/dashboard-page.test.jsx
+++ b/projects/packages/search/tests/js/dashboard/pages/dashboard-page.test.jsx
@@ -8,7 +8,6 @@ jest.mock(
Button: ( { children, ...rest } ) => ,
Container: ( { children } ) => { children }
,
Col: ( { children } ) => { children }
,
- ContextualUpgradeTrigger: ( { children } ) => { children }
,
DonutMeter: () => ,
Gridicon: () => ,
IconTooltip: ( { children } ) => { children }
,
diff --git a/projects/packages/videopress/changelog/change-migrate-cut-wp-ui b/projects/packages/videopress/changelog/change-migrate-cut-wp-ui
new file mode 100644
index 000000000000..b25b23aae75c
--- /dev/null
+++ b/projects/packages/videopress/changelog/change-migrate-cut-wp-ui
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+
+Replace internal ContextualUpgradeTrigger upgrade prompts with @wordpress/ui Notice composition. Internal refactor with a Notice-style visual refresh.
diff --git a/projects/packages/videopress/src/client/admin/components/admin-page/index.tsx b/projects/packages/videopress/src/client/admin/components/admin-page/index.tsx
index 3e8f9272b994..ea63b60545ec 100644
--- a/projects/packages/videopress/src/client/admin/components/admin-page/index.tsx
+++ b/projects/packages/videopress/src/client/admin/components/admin-page/index.tsx
@@ -10,7 +10,6 @@ import {
Button,
Col,
useBreakpointMatch,
- ContextualUpgradeTrigger,
} from '@automattic/jetpack-components';
import {
useProductCheckoutWorkflow,
@@ -19,6 +18,7 @@ import {
} from '@automattic/jetpack-connection';
import { FormFileUpload } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
+import { Notice } from '@wordpress/ui';
import clsx from 'clsx';
import { useState } from 'react';
/**
@@ -246,11 +246,11 @@ const UpgradeTrigger = ( { hasUsedVideo = false }: { hasUsedVideo: boolean } ) =
);
return (
-
+
+ { description && { description } }
+
+ { cta }
+
+
);
};
diff --git a/projects/plugins/protect/changelog/change-migrate-cut-wp-ui b/projects/plugins/protect/changelog/change-migrate-cut-wp-ui
new file mode 100644
index 000000000000..b25b23aae75c
--- /dev/null
+++ b/projects/plugins/protect/changelog/change-migrate-cut-wp-ui
@@ -0,0 +1,4 @@
+Significance: patch
+Type: changed
+
+Replace internal ContextualUpgradeTrigger upgrade prompts with @wordpress/ui Notice composition. Internal refactor with a Notice-style visual refresh.
diff --git a/projects/plugins/protect/src/js/components/threats-list/free-list.jsx b/projects/plugins/protect/src/js/components/threats-list/free-list.jsx
index 76cde0a0e02b..68e220ccfe81 100644
--- a/projects/plugins/protect/src/js/components/threats-list/free-list.jsx
+++ b/projects/plugins/protect/src/js/components/threats-list/free-list.jsx
@@ -1,9 +1,10 @@
-import { Text, Button, ContextualUpgradeTrigger } from '@automattic/jetpack-components';
+import { Text, Button } from '@automattic/jetpack-components';
import { __, sprintf } from '@wordpress/i18n';
import { useCallback } from 'react';
import useAnalyticsTracks from '../../hooks/use-analytics-tracks';
import usePlan from '../../hooks/use-plan';
import FreeAccordion, { FreeAccordionItem } from '../free-accordion';
+import UpgradeNotice from '../upgrade-notice';
import Pagination from './pagination';
import styles from './styles.module.scss';
@@ -65,7 +66,7 @@ const ThreatAccordionItem = ( {
sprintf( __( 'Update to %1$s %2$s', 'jetpack-protect' ), name, fixedIn )
}
- ;
+ /**
+ * Optional href. When set, renders an ActionLink instead of an ActionButton.
+ */
+ href?: string;
+ /**
+ * Whether to open the link in a new tab. Only applies when `href` is set.
+ */
+ openInNewTab?: boolean;
+ /**
+ * Forwarded to the underlying Notice.Root for layout overrides.
+ */
+ className?: string;
+}
+
+/**
+ * Package-local upgrade-notice helper, built on `@wordpress/ui` `Notice`.
+ *
+ * Wraps the `Notice.Root` + `Notice.Description` + `Notice.Actions` composition so the
+ * three Protect upgrade-trigger sites stay terse. Replaces the deprecated
+ * `ContextualUpgradeTrigger` from `@automattic/jetpack-components`.
+ *
+ * @param props - Component properties.
+ * @param props.description - Body copy describing the upgrade context.
+ * @param props.cta - CTA label for the action.
+ * @param props.onClick - Click handler for the CTA (used when `href` is unset).
+ * @param props.href - Optional href. When set, renders an ActionLink.
+ * @param props.openInNewTab - Whether to open the link in a new tab. Only applies when `href` is set.
+ * @param props.className - Optional class forwarded to the underlying Notice.Root.
+ * @return The rendered upgrade notice.
+ */
+const UpgradeNotice: FC< UpgradeNoticeProps > = ( {
+ description,
+ cta,
+ onClick,
+ href,
+ openInNewTab = false,
+ className,
+} ) => {
+ return (
+
+ { description }
+
+ { href !== undefined ? (
+
+ { cta }
+
+ ) : (
+ { cta }
+ ) }
+
+
+ );
+};
+
+export default UpgradeNotice;
diff --git a/projects/plugins/protect/src/js/routes/firewall/index.jsx b/projects/plugins/protect/src/js/routes/firewall/index.jsx
index b261029e3119..1a6015eacef3 100644
--- a/projects/plugins/protect/src/js/routes/firewall/index.jsx
+++ b/projects/plugins/protect/src/js/routes/firewall/index.jsx
@@ -4,7 +4,6 @@ import {
Container,
Text,
ToggleControl,
- ContextualUpgradeTrigger,
useBreakpointMatch,
} from '@automattic/jetpack-components';
import { Popover } from '@wordpress/components';
@@ -15,6 +14,7 @@ import { Notice } from '@wordpress/ui';
import moment from 'moment';
import { useCallback, useEffect, useState, useMemo } from 'react';
import Textarea from '../../components/textarea';
+import UpgradeNotice from '../../components/upgrade-notice';
import { FREE_PLUGIN_SUPPORT_URL, PAID_PLUGIN_SUPPORT_URL } from '../../constants';
import useWafUpgradeSeenMutation from '../../data/waf/use-waf-upgrade-seen-mutation';
import useAnalyticsTracks from '../../hooks/use-analytics-tracks';
@@ -350,7 +350,7 @@ const FirewallPage = () => {
{ ! hasPlan && (
- {
) }
-