From 3a6f9cc3838d9d210133ab65dbac4dde5b138c9a Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Sat, 18 Apr 2026 11:07:50 -0400 Subject: [PATCH 1/6] Remove Gridicon component from js-packages/components and replace usages with @wordpress/icons Replace all usages of the Gridicon component exported from @automattic/jetpack-components with the Icon component and named icons from @wordpress/icons. Removes the Gridicon component from js-packages/components entirely. --- .../components/boost-score-bar/index.tsx | 6 +- .../components/components/gridicon/index.tsx | 334 ------------------ .../gridicon/stories/index.stories.tsx | 20 -- .../components/components/gridicon/style.scss | 16 - .../components/components/gridicon/types.ts | 48 --- .../components/icon-tooltip/index.tsx | 6 +- .../components/icon-tooltip/types.ts | 7 +- .../components/testimonials/index.tsx | 6 +- projects/js-packages/components/index.ts | 1 - .../celebrate-launch-modal.js | 5 +- .../_inc/components/info-tooltip/index.tsx | 10 +- .../protect-card/scan-threats-status.tsx | 4 +- .../src/dashboard/components/card/index.jsx | 9 +- .../donut-meter-container/index.jsx | 11 +- .../mocked-search/mocked-instant-search.jsx | 6 +- .../mocked-search/mocked-legacy-search.jsx | 4 +- .../src/dashboard/components/notice/index.jsx | 27 +- .../components/notice/notice-action.jsx | 6 +- .../pages/sections/first-run-section.jsx | 1 - .../components/record-meter/record-count.jsx | 8 +- .../jetpack/_inc/client/security/sso.jsx | 5 +- .../routes/firewall/firewall-subheading.jsx | 3 +- 22 files changed, 50 insertions(+), 493 deletions(-) delete mode 100644 projects/js-packages/components/components/gridicon/index.tsx delete mode 100644 projects/js-packages/components/components/gridicon/stories/index.stories.tsx delete mode 100644 projects/js-packages/components/components/gridicon/style.scss delete mode 100644 projects/js-packages/components/components/gridicon/types.ts diff --git a/projects/js-packages/components/components/boost-score-bar/index.tsx b/projects/js-packages/components/components/boost-score-bar/index.tsx index de6060bbf207..486799dbbd61 100644 --- a/projects/js-packages/components/components/boost-score-bar/index.tsx +++ b/projects/js-packages/components/components/boost-score-bar/index.tsx @@ -1,6 +1,6 @@ import { __ } from '@wordpress/i18n'; +import { Icon, desktop, mobile } from '@wordpress/icons'; import clsx from 'clsx'; -import Gridicon from '../gridicon/index.tsx'; import type { BoostScoreBarProps } from './types.ts'; import type { FunctionComponent } from 'react'; @@ -25,10 +25,10 @@ export const BoostScoreBar: FunctionComponent< BoostScoreBarProps > = ( { const getIcon = () => { if ( scoreBarType === 'desktop' ) { - return ; + return ; } - return ; + return ; }; const getFillColor = () => { diff --git a/projects/js-packages/components/components/gridicon/index.tsx b/projects/js-packages/components/components/gridicon/index.tsx deleted file mode 100644 index 9eb9cae74619..000000000000 --- a/projects/js-packages/components/components/gridicon/index.tsx +++ /dev/null @@ -1,334 +0,0 @@ -/* !!! -This is a fork of the Jetpack Gridicon code: - https://github.com/Automattic/jetpack/blob/f8078c2cd12ac508334da2fb08e37a92cf283c14/_inc/client/components/gridicon/index.jsx - -It has been modified to work with Preact, and only includes the icons that we need. -!!! */ - -import { __ } from '@wordpress/i18n'; -import clsx from 'clsx'; -import { Component } from 'react'; -import './style.scss'; -import { GridiconProps } from './types.ts'; - -class Gridicon extends Component< GridiconProps > { - static defaultProps = { - 'aria-hidden': 'false', - focusable: 'true', - }; - - needsOffset( icon, size ) { - const iconNeedsOffset = [ - 'gridicons-arrow-left', - 'gridicons-arrow-right', - 'gridicons-calendar', - 'gridicons-cart', - 'gridicons-folder', - 'gridicons-help-outline', - 'gridicons-info', - 'gridicons-info-outline', - 'gridicons-posts', - 'gridicons-star-outline', - 'gridicons-star', - ]; - - if ( iconNeedsOffset.indexOf( icon ) >= 0 ) { - return size % 18 === 0; - } - return false; - } - - getSVGDescription( icon ) { - // Enable overriding desc with falsy/truthy values. - if ( 'description' in this.props ) { - return this.props.description; - } - - switch ( icon ) { - default: - return ''; - case 'gridicons-audio': - return __( 'Has audio', 'jetpack-components' ); - case 'gridicons-arrow-left': - return __( 'Arrow left', 'jetpack-components' ); - case 'gridicons-arrow-right': - return __( 'Arrow right', 'jetpack-components' ); - case 'gridicons-calendar': - return __( 'Is an event', 'jetpack-components' ); - case 'gridicons-cart': - return __( 'Is a product', 'jetpack-components' ); - case 'chevron-down': - return __( 'Show filters', 'jetpack-components' ); - case 'gridicons-comment': - return __( 'Matching comment', 'jetpack-components' ); - case 'gridicons-cross': - return __( 'Close', 'jetpack-components' ); - case 'gridicons-domains': - return __( 'Website', 'jetpack-components' ); - case 'gridicons-filter': - return __( 'Toggle search filters', 'jetpack-components' ); - case 'gridicons-folder': - return __( 'Category', 'jetpack-components' ); - case 'gridicons-help-outline': - return __( 'Help', 'jetpack-components' ); - case 'gridicons-info': - case 'gridicons-info-outline': - return __( 'Information', 'jetpack-components' ); - case 'gridicons-image-multiple': - return __( 'Has multiple images', 'jetpack-components' ); - case 'gridicons-image': - return __( 'Has an image', 'jetpack-components' ); - case 'gridicons-page': - return __( 'Page', 'jetpack-components' ); - case 'gridicons-post': - return __( 'Post', 'jetpack-components' ); - case 'gridicons-jetpack-search': - case 'gridicons-search': - return __( 'Magnifying Glass', 'jetpack-components' ); - case 'gridicons-tag': - return __( 'Tag', 'jetpack-components' ); - case 'gridicons-video': - return __( 'Has a video', 'jetpack-components' ); - } - } - - renderIcon( icon ) { - switch ( icon ) { - default: - return null; - case 'gridicons-audio': - return ( - - - - ); - case 'gridicons-arrow-left': - return ( - - - - ); - case 'gridicons-arrow-right': - return ( - - - - ); - case 'gridicons-block': - return ( - - - - ); - case 'gridicons-calendar': - return ( - - - - ); - case 'gridicons-cart': - return ( - - - - ); - case 'gridicons-checkmark': - return ( - - - - ); - case 'gridicons-chevron-left': - return ( - - - - ); - case 'gridicons-chevron-right': - return ( - - - - ); - case 'gridicons-chevron-down': - return ( - - - - ); - case 'gridicons-comment': - return ( - - - - ); - case 'gridicons-computer': - return ( - - - - ); - case 'gridicons-cross': - return ( - - - - ); - case 'gridicons-domains': - return ( - - - - ); - case 'gridicons-filter': - return ( - - - - ); - case 'gridicons-folder': - return ( - - - - ); - case 'gridicons-help-outline': - return ( - - - - ); - case 'gridicons-image': - return ( - - - - ); - case 'gridicons-image-multiple': - return ( - - - - ); - case 'gridicons-info': - return ( - - - - ); - case 'gridicons-info-outline': - return ( - - - - ); - case 'gridicons-jetpack-search': - return ( - - - - ); - case 'gridicons-phone': - return ( - - - - ); - case 'gridicons-pages': - return ( - - - - ); - case 'gridicons-posts': - return ( - - - - ); - case 'gridicons-search': - return ( - - - - ); - case 'gridicons-star-outline': - return ( - - - - ); - case 'gridicons-star': - return ( - - - - ); - case 'gridicons-tag': - return ( - - - - ); - case 'gridicons-video': - return ( - - - - ); - case 'gridicons-lock': - return ( - <> - - - - - - ); - case 'gridicons-external': - return ( - - - - ); - } - } - - render() { - const { size = 24, className = '' } = this.props; - - const height = this.props.height || size; - const width = this.props.width || size; - const style = this.props.style || { height, width }; - - const icon = 'gridicons-' + this.props.icon; - - const iconClass = clsx( 'gridicon', icon, className, { - 'needs-offset': this.needsOffset( icon, size ), - } ); - const description = this.getSVGDescription( icon ); - - return ( - - { description ? { description } : null } - { this.renderIcon( icon ) } - - ); - } -} - -export default Gridicon; diff --git a/projects/js-packages/components/components/gridicon/stories/index.stories.tsx b/projects/js-packages/components/components/gridicon/stories/index.stories.tsx deleted file mode 100644 index 4c63cab9e71d..000000000000 --- a/projects/js-packages/components/components/gridicon/stories/index.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import Gridicon from '../index.tsx'; -import type { StoryFn, Meta } from '@storybook/react'; - -const meta: Meta< typeof Gridicon > = { - title: 'JS Packages/Components/Gridicon', - component: Gridicon, -}; - -export default meta; - -// Export additional stories using pre-defined values -const Template: StoryFn< typeof Gridicon > = args => ; - -// Export Default story -export const _default = Template.bind( {} ); - -export const InfoOutline = Template.bind( {} ); -InfoOutline.args = { - icon: 'info-outline', -}; diff --git a/projects/js-packages/components/components/gridicon/style.scss b/projects/js-packages/components/components/gridicon/style.scss deleted file mode 100644 index 2be20ebde1fb..000000000000 --- a/projects/js-packages/components/components/gridicon/style.scss +++ /dev/null @@ -1,16 +0,0 @@ -.gridicon { - fill: currentColor; - display: inline-block; - - &.needs-offset g { - transform: translate(1px, 1px); /* translates to .5px because it's in a child element */ - } - - &.needs-offset-x g { - transform: translate(1px, 0); /* only nudges horizontally */ - } - - &.needs-offset-y g { - transform: translate(0, 1px); /* only nudges vertically */ - } -} diff --git a/projects/js-packages/components/components/gridicon/types.ts b/projects/js-packages/components/components/gridicon/types.ts deleted file mode 100644 index e426ea0af980..000000000000 --- a/projects/js-packages/components/components/gridicon/types.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { CSSProperties } from 'react'; - -export type GridiconProps = { - /** - * Icon name - */ - icon: string; - - /** - * HTML class name - */ - className?: string; - - /** - * Description for SVG for screen readers - */ - description?: string; - - /** - * Whether SVG is focussable - */ - focusable?: boolean; - - /** - * SVG height - */ - height?: number; - - /** - * Click handler - */ - onClick?: VoidFunction; - - /** - * SVG width and height - */ - size?: number; - - /** - * SVG style - */ - style?: CSSProperties; - - /** - * SVG width - */ - width?: number; -}; diff --git a/projects/js-packages/components/components/icon-tooltip/index.tsx b/projects/js-packages/components/components/icon-tooltip/index.tsx index 1919097f6ed6..36df64663b45 100644 --- a/projects/js-packages/components/components/icon-tooltip/index.tsx +++ b/projects/js-packages/components/components/icon-tooltip/index.tsx @@ -1,8 +1,8 @@ import { Popover } from '@wordpress/components'; +import { Icon, info } from '@wordpress/icons'; import clsx from 'clsx'; import { useCallback, useState, ReactElement, FC } from 'react'; import Button from '../button/index.tsx'; -import Gridicon from '../gridicon/index.tsx'; import { IconTooltipProps, Placement, Position } from './types.ts'; import './style.scss'; @@ -31,7 +31,7 @@ const IconTooltip: FC< IconTooltipProps > = ( { iconClassName = '', placement = 'bottom-end', animate = true, - iconCode = 'info-outline', + iconCode = info, iconSize = 18, offset = 10, title, @@ -109,7 +109,7 @@ const IconTooltip: FC< IconTooltipProps > = ( { > { ! isAnchorWrapper && ( ) }
{ className="testimonials__left-arrow" onClick={ decrementTestimonial } > - + ) } @@ -48,7 +48,7 @@ const Testimonials: TestimonialsType = ( { testimonials } ) => { className="testimonials__right-arrow" onClick={ incrementTestimonial } > - + ) }
diff --git a/projects/js-packages/components/index.ts b/projects/js-packages/components/index.ts index d95d1e408014..b1b03e1282a1 100644 --- a/projects/js-packages/components/index.ts +++ b/projects/js-packages/components/index.ts @@ -27,7 +27,6 @@ export { default as AutomatticForAgenciesLogo } from './components/automattic-fo export { default as JetpackFooter } from './components/jetpack-footer/index.tsx'; /** @deprecated Use `Spinner` from `@wordpress/components` instead. */ export { default as Spinner } from './components/spinner/index.tsx'; -export { default as Gridicon } from './components/gridicon/index.tsx'; export { default as IconTooltip } from './components/icon-tooltip/index.tsx'; export { default as ActionButton } from './components/action-button/index.tsx'; export { default as PricingCard } from './components/pricing-card/index.tsx'; diff --git a/projects/packages/jetpack-mu-wpcom/src/common/celebrate-launch/celebrate-launch-modal.js b/projects/packages/jetpack-mu-wpcom/src/common/celebrate-launch/celebrate-launch-modal.js index 6474769447a0..0ad14e8dea03 100644 --- a/projects/packages/jetpack-mu-wpcom/src/common/celebrate-launch/celebrate-launch-modal.js +++ b/projects/packages/jetpack-mu-wpcom/src/common/celebrate-launch/celebrate-launch-modal.js @@ -1,9 +1,8 @@ -import { Gridicon } from '@automattic/jetpack-components'; import { Button, Modal, Tooltip } from '@wordpress/components'; import { useCopyToClipboard } from '@wordpress/compose'; import { useState, useEffect, createInterpolateElement } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { Icon, copy } from '@wordpress/icons'; +import { Icon, copy, globe } from '@wordpress/icons'; import { wpcomTrackEvent } from '../tracks'; import ConfettiAnimation from './confetti-animation'; @@ -153,7 +152,7 @@ export default function CelebrateLaunchModal( { { isPopoverVisible && ( = ( { data, numThreats, criticalThre onClick={ toggleTooltip } ref={ useTooltipRef } > - + { criticalThreatCount } { isPopoverVisible && ( diff --git a/projects/packages/search/src/dashboard/components/card/index.jsx b/projects/packages/search/src/dashboard/components/card/index.jsx index c40fe8ee67e6..bed02dff637f 100644 --- a/projects/packages/search/src/dashboard/components/card/index.jsx +++ b/projects/packages/search/src/dashboard/components/card/index.jsx @@ -1,4 +1,4 @@ -import { Gridicon } from '@automattic/jetpack-components'; +import { Icon, external as externalIcon, chevronRight } from '@wordpress/icons'; import clsx from 'clsx'; import PropTypes from 'prop-types'; import { Component, createElement } from 'react'; @@ -81,9 +81,9 @@ class Card extends Component { let linkIndicator; if ( this.props.href ) { linkIndicator = ( - ); } else { @@ -118,9 +118,6 @@ class Card extends Component { _renderIcon = () => { return ( - { this.props.icon && ( - - ) } { this.props.iconLabel } ); diff --git a/projects/packages/search/src/dashboard/components/donut-meter-container/index.jsx b/projects/packages/search/src/dashboard/components/donut-meter-container/index.jsx index 8beeaa4db74f..eae86ad0b09c 100644 --- a/projects/packages/search/src/dashboard/components/donut-meter-container/index.jsx +++ b/projects/packages/search/src/dashboard/components/donut-meter-container/index.jsx @@ -1,12 +1,7 @@ -import { - DonutMeter, - Gridicon, - IconTooltip, - Button, - ThemeProvider, -} from '@automattic/jetpack-components'; +import { DonutMeter, IconTooltip, Button, ThemeProvider } from '@automattic/jetpack-components'; import { formatNumber as formatNumberImported } from '@automattic/number-formatters'; import { __ } from '@wordpress/i18n'; +import { Icon, info } from '@wordpress/icons'; import './style.scss'; const localizedUnlimited = __( 'Unlimited', 'jetpack-search-pkg' ); @@ -122,7 +117,7 @@ const InfoPrimary = ( { localizedMessage, iconClickedCallback } ) => { { localizedMessage }{ ' ' } { haveCallback && ( - + ) } diff --git a/projects/packages/search/src/dashboard/components/mocked-search/mocked-instant-search.jsx b/projects/packages/search/src/dashboard/components/mocked-search/mocked-instant-search.jsx index 945f037d7ff3..3f79089ac03d 100644 --- a/projects/packages/search/src/dashboard/components/mocked-search/mocked-instant-search.jsx +++ b/projects/packages/search/src/dashboard/components/mocked-search/mocked-instant-search.jsx @@ -1,5 +1,5 @@ -import { Gridicon } from '@automattic/jetpack-components'; import { __, sprintf } from '@wordpress/i18n'; +import { Icon, search as searchIcon, close } from '@wordpress/icons'; import { useId } from 'react'; import TextRowPlaceHolder from './placeholder'; import './mocked-instant-search.scss'; @@ -14,13 +14,13 @@ export default function MockedInstantSearch() {