diff --git a/projects/js-packages/components/changelog/change-migrate-status-wp-ui b/projects/js-packages/components/changelog/change-migrate-status-wp-ui new file mode 100644 index 000000000000..bec61ec14e93 --- /dev/null +++ b/projects/js-packages/components/changelog/change-migrate-status-wp-ui @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Components: deprecate Status; inline @wordpress/ui Text in consumers. diff --git a/projects/js-packages/components/components/status/index.tsx b/projects/js-packages/components/components/status/index.tsx index b370cc4312c7..a0b4db9bd715 100644 --- a/projects/js-packages/components/components/status/index.tsx +++ b/projects/js-packages/components/components/status/index.tsx @@ -10,6 +10,17 @@ export interface StatusProps { className?: string; } +/** + * Status component. + * + * @deprecated Inline the equivalent JSX using `Text` from `@wordpress/ui` and a small color-coded indicator span. The wrapper renders a flex container at `body-sm` size with `font-weight: 600` and a `0.666em` round indicator coloured by status using WPDS design tokens (`var(--wpds-color-fg-content-success-weak)` for `active`, `--wpds-color-fg-content-error-weak` for `error`, `--wpds-color-fg-content-neutral-weak` for `inactive`, `--wpds-color-fg-content-warning-weak` for `action`, `--wpds-color-fg-content-info-weak` for `initializing`). Include a fallback hex for surfaces that don't load `@wordpress/theme/design-tokens.css` (e.g. the legacy Jetpack settings dashboard). + * + * @param {StatusProps} props - The component properties. + * @param {string} props.className - Optional className forwarded to the outer element. + * @param {string} props.label - Status label. Defaults to a status-derived string. + * @param {string} props.status - Status key: `active | error | inactive | action | initializing`. + * @return {JSX.Element} The `Status` component. + */ const Status = ( { className, label, status = 'inactive' }: StatusProps ): JSX.Element => { const defaultLabels: Record< string, string > = { active: __( 'Active', 'jetpack-components' ), diff --git a/projects/plugins/jetpack/_inc/client/pro-status/index.jsx b/projects/plugins/jetpack/_inc/client/pro-status/index.jsx index ad1e9bb2ba1c..3dba0f998eaa 100644 --- a/projects/plugins/jetpack/_inc/client/pro-status/index.jsx +++ b/projects/plugins/jetpack/_inc/client/pro-status/index.jsx @@ -1,5 +1,7 @@ -import { Status, getRedirectUrl } from '@automattic/jetpack-components'; +import { getRedirectUrl } from '@automattic/jetpack-components'; import { __, _n, _x } from '@wordpress/i18n'; +import { Text } from '@wordpress/ui'; +import clsx from 'clsx'; import PropTypes from 'prop-types'; import { Component } from 'react'; import { connect } from 'react-redux'; @@ -22,6 +24,30 @@ import { getRewindStatus } from 'state/rewind'; import { getScanStatus } from 'state/scan'; import { getSitePlan, siteHasFeature, isFetchingSiteData } from 'state/site'; import { isFetchingPluginsData, isPluginActive, isPluginInstalled } from 'state/site/plugins'; +import styles from './style.module.scss'; + +/** + * Render a small status indicator with a coloured dot and label. + * + * @param {object} props - Component props. + * @param {string} props.status - Status key. + * @param {React.ReactNode} props.label - Label content. + * @return {import('react').ReactElement} The status indicator. + */ +const StatusIndicator = ( { status, label } ) => ( + + + { label } + +); + +const DEFAULT_LABELS = { + active: __( 'Active', 'jetpack' ), + error: __( 'Error', 'jetpack' ), + action: __( 'Action needed', 'jetpack' ), + inactive: __( 'Inactive', 'jetpack' ), + initializing: __( 'Setting up', 'jetpack' ), +}; /** * Track click on Pro status badge. @@ -110,10 +136,15 @@ class ProStatus extends Component { return; case 'rewind_connected': { const rewindMessage = this.getRewindMessage(); - return ; + return ( + + ); } case 'active': - return ; + return ; } const label = ( @@ -131,7 +162,7 @@ class ProStatus extends Component { ); - return ; + return ; }; /** @@ -209,7 +240,7 @@ class ProStatus extends Component { } else if ( scanStatus && scanStatus.state !== 'unavailable' ) { if ( Array.isArray( scanStatus.threats ) && scanStatus.threats.length > 0 ) { return ( - @@ -219,7 +250,7 @@ class ProStatus extends Component { return ''; } if ( scanStatus.credentials.length === 0 ) { - return ; + return ; } return this.getProActions( 'secure', 'scan' ); } diff --git a/projects/plugins/jetpack/_inc/client/pro-status/style.module.scss b/projects/plugins/jetpack/_inc/client/pro-status/style.module.scss new file mode 100644 index 000000000000..829b86a4e3be --- /dev/null +++ b/projects/plugins/jetpack/_inc/client/pro-status/style.module.scss @@ -0,0 +1,56 @@ +.status { + align-items: center; + display: inline-flex; + font-weight: 600; + line-height: 1.666; + white-space: nowrap; + + &.is-active { + color: var(--wpds-color-fg-content-success-weak, #008030); + + .indicator { + background-color: var(--wpds-color-fg-content-success-weak, #008030); + } + } + + &.is-inactive { + color: var(--wpds-color-fg-content-neutral-weak, #707070); + + .indicator { + background-color: var(--wpds-color-fg-content-neutral-weak, #707070); + } + } + + &.is-error { + color: var(--wpds-color-fg-content-error-weak, #cc1818); + + .indicator { + background-color: var(--wpds-color-fg-content-error-weak, #cc1818); + } + } + + &.is-action { + color: var(--wpds-color-fg-content-warning-weak, #926300); + + .indicator { + background-color: var(--wpds-color-fg-content-warning-weak, #926300); + } + } + + &.is-initializing { + color: var(--wpds-color-fg-content-info-weak, #006bd7); + + .indicator { + background-color: var(--wpds-color-fg-content-info-weak, #006bd7); + } + } +} + +.indicator { + background-color: var(--wpds-color-fg-content-neutral-weak, #707070); + border-radius: 50%; + flex-shrink: 0; + height: 0.666em; + margin-right: 4px; + width: 0.666em; +} diff --git a/projects/plugins/jetpack/_inc/client/security/style.scss b/projects/plugins/jetpack/_inc/client/security/style.scss index 38e89cc74342..0b9ab21b774f 100644 --- a/projects/plugins/jetpack/_inc/client/security/style.scss +++ b/projects/plugins/jetpack/_inc/client/security/style.scss @@ -9,7 +9,22 @@ display: flex; .waf__standalone__mode { + align-items: center; + color: var(--wpds-color-fg-content-success-weak, #008030); + display: inline-flex; + font-weight: 600; + line-height: 1.666; margin-left: auto; + white-space: nowrap; + + .waf__standalone__mode__indicator { + background-color: var(--wpds-color-fg-content-success-weak, #008030); + border-radius: 50%; + flex-shrink: 0; + height: 0.666em; + margin-right: 4px; + width: 0.666em; + } } } diff --git a/projects/plugins/jetpack/_inc/client/security/waf.jsx b/projects/plugins/jetpack/_inc/client/security/waf.jsx index 3315ec00148a..2c73cbb4907d 100644 --- a/projects/plugins/jetpack/_inc/client/security/waf.jsx +++ b/projects/plugins/jetpack/_inc/client/security/waf.jsx @@ -1,8 +1,8 @@ -import { getRedirectUrl, Status } from '@automattic/jetpack-components'; +import { getRedirectUrl } from '@automattic/jetpack-components'; import { ToggleControl } from '@wordpress/components'; import { createInterpolateElement } from '@wordpress/element'; import { __, _x, sprintf } from '@wordpress/i18n'; -import { Link } from '@wordpress/ui'; +import { Link, Text } from '@wordpress/ui'; import { Component } from 'react'; import { connect } from 'react-redux'; import Button from 'components/button'; @@ -206,11 +206,10 @@ export const Waf = class extends Component {
{ _x( 'Firewall', 'Settings header', 'jetpack' ) } { this.props.settings?.standaloneMode && ( - + + + { __( 'Standalone mode', 'jetpack' ) } + ) }
); diff --git a/projects/plugins/jetpack/changelog/change-migrate-status-wp-ui b/projects/plugins/jetpack/changelog/change-migrate-status-wp-ui new file mode 100644 index 000000000000..0db43b2fd7e1 --- /dev/null +++ b/projects/plugins/jetpack/changelog/change-migrate-status-wp-ui @@ -0,0 +1,4 @@ +Significance: patch +Type: compat + +Jetpack: migrate Status indicator to @wordpress/ui Text. diff --git a/projects/plugins/protect/changelog/change-migrate-status-wp-ui b/projects/plugins/protect/changelog/change-migrate-status-wp-ui new file mode 100644 index 000000000000..a9cf6c8f48dc --- /dev/null +++ b/projects/plugins/protect/changelog/change-migrate-status-wp-ui @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Protect: migrate Status indicator to @wordpress/ui Text. diff --git a/projects/plugins/protect/src/js/components/admin-section-hero/index.tsx b/projects/plugins/protect/src/js/components/admin-section-hero/index.tsx index 1d176867c602..8d2b77f56d9b 100644 --- a/projects/plugins/protect/src/js/components/admin-section-hero/index.tsx +++ b/projects/plugins/protect/src/js/components/admin-section-hero/index.tsx @@ -3,6 +3,8 @@ import { H3, getIconBySlug, } from '@automattic/jetpack-components'; +import { Text as UIText } from '@wordpress/ui'; +import clsx from 'clsx'; import SeventyFiveLayout from '../seventy-five-layout'; import AdminSectionHeroNotices from './admin-section-hero-notices'; import styles from './styles.module.scss'; @@ -15,9 +17,15 @@ interface AdminSectionHeroProps { spacing?: number; } +interface StatusIndicatorProps { + status: 'active' | 'inactive'; + label: ReactNode; +} + interface AdminSectionHeroComponent extends FC< AdminSectionHeroProps > { Heading: FC< { children: ReactNode; showIcon?: boolean } >; Subheading: FC< { children: ReactNode } >; + StatusIndicator: FC< StatusIndicatorProps >; } const AdminSectionHero: AdminSectionHeroComponent = ( { @@ -64,4 +72,13 @@ AdminSectionHero.Subheading = ( { children }: { children: ReactNode } ) => { return
{ children }
; }; +AdminSectionHero.StatusIndicator = ( { status, label }: StatusIndicatorProps ) => { + return ( + + + { label } + + ); +}; + export default AdminSectionHero; diff --git a/projects/plugins/protect/src/js/components/admin-section-hero/stories/index.stories.jsx b/projects/plugins/protect/src/js/components/admin-section-hero/stories/index.stories.jsx index 7d5b4f8066c9..524ebb509add 100644 --- a/projects/plugins/protect/src/js/components/admin-section-hero/stories/index.stories.jsx +++ b/projects/plugins/protect/src/js/components/admin-section-hero/stories/index.stories.jsx @@ -1,4 +1,4 @@ -import { Status, Text } from '@automattic/jetpack-components'; +import { Text } from '@automattic/jetpack-components'; import AdminSectionHero from '..'; import InProgressAnimation from '../../in-progress-animation'; @@ -11,7 +11,7 @@ export const Default = args => ; Default.args = { main: ( <> - + { 'No threats found' } { 'Most recent results' } diff --git a/projects/plugins/protect/src/js/components/admin-section-hero/styles.module.scss b/projects/plugins/protect/src/js/components/admin-section-hero/styles.module.scss index 566f57bad886..6d31f53ef1bd 100644 --- a/projects/plugins/protect/src/js/components/admin-section-hero/styles.module.scss +++ b/projects/plugins/protect/src/js/components/admin-section-hero/styles.module.scss @@ -24,3 +24,36 @@ .connection-error-col { margin-top: calc(var(--spacing-base) * 3 + 1px); // 25px } + +.status { + align-items: center; + display: inline-flex; + font-weight: 600; + line-height: 1.666; + white-space: nowrap; + + &.is-active { + color: var(--wpds-color-fg-content-success-weak, #008030); + + .indicator { + background-color: var(--wpds-color-fg-content-success-weak, #008030); + } + } + + &.is-inactive { + color: var(--wpds-color-fg-content-neutral-weak, #707070); + + .indicator { + background-color: var(--wpds-color-fg-content-neutral-weak, #707070); + } + } +} + +.indicator { + background-color: var(--wpds-color-fg-content-neutral-weak, #707070); + border-radius: 50%; + flex-shrink: 0; + height: 0.666em; + margin-right: 4px; + width: 0.666em; +} diff --git a/projects/plugins/protect/src/js/routes/firewall/firewall-admin-section-hero.tsx b/projects/plugins/protect/src/js/routes/firewall/firewall-admin-section-hero.tsx index a8efa2587de9..b66437dc2d5c 100644 --- a/projects/plugins/protect/src/js/routes/firewall/firewall-admin-section-hero.tsx +++ b/projects/plugins/protect/src/js/routes/firewall/firewall-admin-section-hero.tsx @@ -1,4 +1,4 @@ -import { Status, Text } from '@automattic/jetpack-components'; +import { Text } from '@automattic/jetpack-components'; import { __, _x } from '@wordpress/i18n'; import { useMemo } from 'react'; import AdminSectionHero from '../../components/admin-section-hero'; @@ -83,11 +83,13 @@ const FirewallAdminSectionHero = () => { return ; }, [ status ] ); + const indicatorStatus = 'on' === status ? 'active' : 'inactive'; + return ( - + { heading } { subheading } diff --git a/projects/plugins/protect/src/js/routes/scan/history/history-admin-section-hero.tsx b/projects/plugins/protect/src/js/routes/scan/history/history-admin-section-hero.tsx index ef7176423c4b..07d0461c7cbe 100644 --- a/projects/plugins/protect/src/js/routes/scan/history/history-admin-section-hero.tsx +++ b/projects/plugins/protect/src/js/routes/scan/history/history-admin-section-hero.tsx @@ -1,4 +1,4 @@ -import { Status, Text } from '@automattic/jetpack-components'; +import { Text } from '@automattic/jetpack-components'; import { dateI18n } from '@wordpress/date'; import { __, sprintf } from '@wordpress/i18n'; import { useMemo } from 'react'; @@ -49,7 +49,10 @@ const HistoryAdminSectionHero: FC = () => { - + { numAllThreats > 0 ? sprintf( diff --git a/projects/plugins/protect/src/js/routes/scan/scan-admin-section-hero.tsx b/projects/plugins/protect/src/js/routes/scan/scan-admin-section-hero.tsx index 41a06db94b7c..616ab29e8c0c 100644 --- a/projects/plugins/protect/src/js/routes/scan/scan-admin-section-hero.tsx +++ b/projects/plugins/protect/src/js/routes/scan/scan-admin-section-hero.tsx @@ -1,4 +1,4 @@ -import { Text, Status, useBreakpointMatch } from '@automattic/jetpack-components'; +import { Text, useBreakpointMatch } from '@automattic/jetpack-components'; import { dateI18n } from '@wordpress/date'; import { __, _n, _x, sprintf } from '@wordpress/i18n'; import { useState } from 'react'; @@ -51,7 +51,10 @@ const ScanAdminSectionHero: FC = () => { - + { numThreats > 0 ? sprintf(