PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.5.0
Presto Player v4.5.0
4.5.0 4.4.1 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / src / admin / dashboard / components / PromoBanner.js
presto-player / src / admin / dashboard / components Last commit date
Emails 3 months ago EngagementChart 3 months ago MediaHub 3 months ago Onboarding 3 months ago Popup 3 months ago Skeletons 2 months ago WhatsNew 3 months ago charts 3 months ago test 3 months ago AdminMenuSync.js 3 months ago ChartEmptyState.js 3 months ago ChooseDate.js 3 months ago ColorPicker.js 3 months ago DashboardPromos.js 2 days ago ExtendPlugins.js 3 months ago Filters.js 3 months ago Link.js 3 months ago McpPromoBanner.js 2 days ago Navbar.js 2 months ago NoFound.js 3 months ago PageHeader.js 3 months ago PluginRecommendations.js 3 months ago PostScheduleField.js 3 months ago PrestoPlayerIcon.js 3 months ago ProGateOverlay.js 3 months ago PromoBanner.js 2 days ago QuickAccess.js 2 weeks ago RankedTable.js 3 months ago SkinPromoBanner.js 2 days ago StatCard.js 3 months ago TopMedia.js 3 months ago TopPerformingMedia.js 3 months ago TopUsers.js 3 months ago TruncatedTitle.js 3 months ago UpgradeNotice.js 3 months ago UpgradeToPro.js 2 weeks ago VideoModal.js 3 months ago WelcomeBanner.js 3 months ago
PromoBanner.js
103 lines
1 import { __ } from '@wordpress/i18n';
2 import { X, ArrowRight } from 'lucide-react';
3
4 // Reading the window.localStorage property itself throws a SecurityError when
5 // site data is blocked, and these banners render above the whole dashboard — so
6 // every touch goes through here.
7 const withStorage = ( callback ) => {
8 try {
9 return callback( window.localStorage );
10 } catch ( e ) {
11 return false;
12 }
13 };
14
15 export const isPromoDismissed = ( storageKey ) =>
16 withStorage( ( store ) => store.getItem( storageKey ) === '1' );
17
18 /**
19 * Full-width promo strip under the navbar. Shared chrome only — each promo owns
20 * its own copy, gating and storage key.
21 *
22 * Visibility is NOT owned here — DashboardPromos decides which promo is on
23 * screen, so dismissing has to tell it rather than just hiding this subtree.
24 *
25 * @param {Object} props
26 * @param {JSX.Element} props.icon Leading icon.
27 * @param {string} props.title Headline.
28 * @param {boolean} props.tag Show the "New" pill beside the title.
29 * @param {Array<string>} props.chips Short example pills. Omit for none.
30 * @param {string} props.ctaLabel Button label. Omit for announcement-only.
31 * @param {string} props.ctaHref Button destination.
32 * @param {string} props.storageKey localStorage key holding the dismissal.
33 * @param {Function} props.onDismiss Called after the dismissal is stored.
34 */
35 const PromoBanner = ( {
36 icon,
37 title,
38 tag = false,
39 chips = [],
40 ctaLabel,
41 ctaHref,
42 storageKey,
43 onDismiss,
44 } ) => {
45 const dismiss = () => {
46 withStorage( ( store ) => store.setItem( storageKey, '1' ) );
47 onDismiss();
48 };
49
50 return (
51 <div className="relative flex flex-col gap-3 border-b border-brand-border-300 bg-gradient-to-r from-brand-background-50 to-white px-6 py-4 md:flex-row md:items-center md:gap-6">
52 <span className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-brand-primary-50">
53 { icon }
54 </span>
55
56 <div className="flex flex-1 flex-col gap-2">
57 <p className="m-0 flex items-center gap-2 text-sm font-semibold text-text-primary">
58 { title }
59 { !! tag && (
60 <span className="shrink-0 rounded-full bg-brand-primary-600 px-1.5 py-px text-[9px] font-semibold uppercase tracking-wide text-white">
61 { __( 'New', 'presto-player' ) }
62 </span>
63 ) }
64 </p>
65 { !! chips.length && (
66 <div className="flex flex-wrap gap-2">
67 { chips.map( ( chip ) => (
68 <span
69 key={ chip }
70 className="inline-flex items-center rounded-full border border-brand-border-300 bg-white px-2.5 py-1 text-xs text-text-secondary"
71 >
72 { chip }
73 </span>
74 ) ) }
75 </div>
76 ) }
77 </div>
78
79 <div className="flex shrink-0 items-center gap-2">
80 { !! ctaLabel && (
81 <a
82 href={ ctaHref }
83 className="inline-flex items-center gap-1.5 rounded-md bg-brand-primary-600 px-3 py-1.5 text-sm font-semibold text-white no-underline hover:opacity-90"
84 >
85 { ctaLabel }
86 <ArrowRight className="size-4" aria-hidden="true" />
87 </a>
88 ) }
89 <button
90 type="button"
91 onClick={ dismiss }
92 aria-label={ __( 'Dismiss', 'presto-player' ) }
93 className="shrink-0 cursor-pointer border-0 bg-transparent p-1 text-icon-secondary hover:text-icon-primary"
94 >
95 <X className="size-4" aria-hidden="true" />
96 </button>
97 </div>
98 </div>
99 );
100 };
101
102 export default PromoBanner;
103