From a6c2cbb6c403d13b81191df9cccccae97c15656b Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Thu, 2 Apr 2026 21:52:06 +0300 Subject: [PATCH 1/6] Forms: use EmptyState component --- .../packages/forms/routes/forms/stage.tsx | 25 +++-- .../forms/src/blocks/contact-form/index.js | 2 +- .../components/empty-responses/index.tsx | 100 +++++++++--------- .../forms/src/dashboard/forms/index.tsx | 23 ++-- 4 files changed, 78 insertions(+), 72 deletions(-) diff --git a/projects/packages/forms/routes/forms/stage.tsx b/projects/packages/forms/routes/forms/stage.tsx index ffe36fe84bf7..156b62aa900e 100644 --- a/projects/packages/forms/routes/forms/stage.tsx +++ b/projects/packages/forms/routes/forms/stage.tsx @@ -14,14 +14,15 @@ import { dateI18n, getSettings as getDateSettings } from '@wordpress/date'; import { useEffect, useMemo, useState, useCallback } from '@wordpress/element'; import { __, _n, sprintf } from '@wordpress/i18n'; import { useSearch, useNavigate } from '@wordpress/route'; -import { Badge } from '@wordpress/ui'; +import { Badge, EmptyState } from '@wordpress/ui'; import * as React from 'react'; /** * Internal dependencies */ import IntegrationsModal from '../../src/blocks/contact-form/components/jetpack-integrations-modal'; +import { icon as formBlockIcon } from '../../src/blocks/contact-form/index.js'; import CreateFormButton from '../../src/dashboard/components/create-form-button/index.tsx'; -import { EmptyWrapper, NoResults } from '../../src/dashboard/components/empty-responses/index.tsx'; +import { NoResults } from '../../src/dashboard/components/empty-responses/index.tsx'; import { FormNameModal } from '../../src/dashboard/components/form-name-modal'; import { FORM_STATUSES, @@ -612,13 +613,15 @@ function StageInner() { hasActiveFilters ? ( ) : ( - + + + { __( "You're set up. No forms yet.", 'jetpack-forms' ) } + + + { __( 'Create a form to manage and reuse it across your site.', 'jetpack-forms' ) } + + ) } - } - /> + + ) } view={ view } diff --git a/projects/packages/forms/src/blocks/contact-form/index.js b/projects/packages/forms/src/blocks/contact-form/index.js index 55f0b37a3e22..3b75e170d0e0 100644 --- a/projects/packages/forms/src/blocks/contact-form/index.js +++ b/projects/packages/forms/src/blocks/contact-form/index.js @@ -48,7 +48,7 @@ export const getFormLabel = ( { ref } ) => { } ); }; -const icon = renderMaterialIcon( +export const icon = renderMaterialIcon( <> diff --git a/projects/packages/forms/src/dashboard/components/empty-responses/index.tsx b/projects/packages/forms/src/dashboard/components/empty-responses/index.tsx index ef149822654a..b87478d9a8f9 100644 --- a/projects/packages/forms/src/dashboard/components/empty-responses/index.tsx +++ b/projects/packages/forms/src/dashboard/components/empty-responses/index.tsx @@ -2,15 +2,12 @@ * External dependencies */ import { isSimpleSite } from '@automattic/jetpack-script-data'; -import { - Button, - __experimentalText as Text, // eslint-disable-line @wordpress/no-unsafe-wp-apis - __experimentalVStack as VStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis -} from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { createInterpolateElement, useCallback, useMemo } from '@wordpress/element'; import { __, _n, sprintf } from '@wordpress/i18n'; -import { Link } from '@wordpress/ui'; +import { page, search, shield, trash } from '@wordpress/icons'; +import { EmptyState, Link } from '@wordpress/ui'; /** * Internal dependencies */ @@ -44,12 +41,6 @@ type EmptyResponsesProps = { status: string; }; -type EmptyWrapperProps = { - heading?: string; - body?: string | ReactNode; - actions?: ReactNode; -}; - /** * Hook to handle Akismet installation and activation. * @@ -152,26 +143,17 @@ const useInstallAkismet = (): UseInstallAkismetReturn => { }; }; -export const EmptyWrapper = ( { heading = '', body = '', actions = null }: EmptyWrapperProps ) => ( - - { heading && ( - - { heading } - - ) } - { body && { body } } - { actions && { actions } } - -); - export const NoResults = () => ( - + + + { __( 'No results found', 'jetpack-forms' ) } + + { __( + "Try adjusting your search or filters to find what you're looking for.", + 'jetpack-forms' + ) } + + ); const EmptyResponses = ( { @@ -209,7 +191,13 @@ const EmptyResponses = ( { ); if ( status === 'trash' ) { return ( - 0 && noTrashMessage } /> + + + { noTrashHeading } + { emptyTrashDays > 0 && ( + { noTrashMessage } + ) } + ); } @@ -222,10 +210,11 @@ const EmptyResponses = ( { if ( status === 'spam' ) { if ( shouldShowAkismetCta ) { return ( - + + { noSpamHeading } + { wrapperBody } + - } - /> + + ); } - return ; + return ( + + + { noSpamHeading } + { noSpamMessage } + + ); } return ( - + + + { __( "You're set up. No responses yet.", 'jetpack-forms' ) } + + + { __( + 'Share your form to start collecting responses. New items will appear here.', + 'jetpack-forms' + ) } + + { ! isSingleFormView && ( + - ) - } - /> + + ) } + ); }; diff --git a/projects/packages/forms/src/dashboard/forms/index.tsx b/projects/packages/forms/src/dashboard/forms/index.tsx index 52c0c9cb3647..eab47a8be2fe 100644 --- a/projects/packages/forms/src/dashboard/forms/index.tsx +++ b/projects/packages/forms/src/dashboard/forms/index.tsx @@ -14,15 +14,16 @@ import { dateI18n, getSettings as getDateSettings } from '@wordpress/date'; import { useCallback, useEffect, useMemo, useState } from '@wordpress/element'; import { __, _n, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; +import { EmptyState } from '@wordpress/ui'; import { useNavigate } from 'react-router'; /** * Internal dependencies */ +import { icon as formBlockIcon } from '../../blocks/contact-form/index.js'; import { getEmbedCode, getShortcode } from '../../blocks/shared/util/embed-codes'; import useConfigValue from '../../hooks/use-config-value.ts'; import CreateFormButton from '../components/create-form-button/index.tsx'; import DataViewsHeaderRow from '../components/dataviews-header-row/index.tsx'; -import { EmptyWrapper } from '../components/empty-responses/index.tsx'; import Page from '../components/page/index.tsx'; import { NON_TRASH_FORM_STATUSES } from '../constants.ts'; import useDeleteForm from '../hooks/use-delete-form.ts'; @@ -442,13 +443,15 @@ export default function FormsDashboardForms(): JSX.Element | null { data={ records || [] } isLoading={ isLoading } empty={ - + + + { __( "You're set up. No forms yet.", 'jetpack-forms' ) } + + + { __( 'Create a form to manage and reuse it across your site.', 'jetpack-forms' ) } + + ) } - } - /> + + } view={ view } onChangeView={ onChangeView } From 602d9342a4e21a3289fbb95276235ebe59e56249 Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Thu, 2 Apr 2026 21:53:29 +0300 Subject: [PATCH 2/6] changelog --- projects/packages/forms/changelog/update-forms-empty-state | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 projects/packages/forms/changelog/update-forms-empty-state diff --git a/projects/packages/forms/changelog/update-forms-empty-state b/projects/packages/forms/changelog/update-forms-empty-state new file mode 100644 index 000000000000..6d19ae2de444 --- /dev/null +++ b/projects/packages/forms/changelog/update-forms-empty-state @@ -0,0 +1,4 @@ +Significance: minor +Type: changed + +Update empty state to use component from wp-ui. From ced1897fc33d731f83ed664011f3e9a44750e2da Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Thu, 28 May 2026 10:43:09 +0300 Subject: [PATCH 3/6] Use Button from wp-ui --- .../src/dashboard/components/empty-responses/index.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/projects/packages/forms/src/dashboard/components/empty-responses/index.tsx b/projects/packages/forms/src/dashboard/components/empty-responses/index.tsx index b87478d9a8f9..146c96f7d99c 100644 --- a/projects/packages/forms/src/dashboard/components/empty-responses/index.tsx +++ b/projects/packages/forms/src/dashboard/components/empty-responses/index.tsx @@ -2,12 +2,11 @@ * External dependencies */ import { isSimpleSite } from '@automattic/jetpack-script-data'; -import { Button } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { createInterpolateElement, useCallback, useMemo } from '@wordpress/element'; import { __, _n, sprintf } from '@wordpress/i18n'; import { page, search, shield, trash } from '@wordpress/icons'; -import { EmptyState, Link } from '@wordpress/ui'; +import { Button, EmptyState, Link } from '@wordpress/ui'; /** * Internal dependencies */ @@ -216,11 +215,10 @@ const EmptyResponses = ( { { wrapperBody } From d507a78ffa6dd08935d789f1c7167a9e5570d135 Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Fri, 29 May 2026 17:44:26 +0300 Subject: [PATCH 4/6] Move icon to its own files to fix the build --- .../packages/forms/routes/forms/stage.tsx | 2 +- .../forms/src/blocks/contact-form/icon.jsx | 24 ++++++++++++++++++ .../forms/src/blocks/contact-form/index.js | 25 +------------------ .../forms/src/dashboard/forms/index.tsx | 2 +- 4 files changed, 27 insertions(+), 26 deletions(-) create mode 100644 projects/packages/forms/src/blocks/contact-form/icon.jsx diff --git a/projects/packages/forms/routes/forms/stage.tsx b/projects/packages/forms/routes/forms/stage.tsx index 156b62aa900e..9eeb16e1fc2c 100644 --- a/projects/packages/forms/routes/forms/stage.tsx +++ b/projects/packages/forms/routes/forms/stage.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; * Internal dependencies */ import IntegrationsModal from '../../src/blocks/contact-form/components/jetpack-integrations-modal'; -import { icon as formBlockIcon } from '../../src/blocks/contact-form/index.js'; +import { icon as formBlockIcon } from '../../src/blocks/contact-form/icon.jsx'; import CreateFormButton from '../../src/dashboard/components/create-form-button/index.tsx'; import { NoResults } from '../../src/dashboard/components/empty-responses/index.tsx'; import { FormNameModal } from '../../src/dashboard/components/form-name-modal'; diff --git a/projects/packages/forms/src/blocks/contact-form/icon.jsx b/projects/packages/forms/src/blocks/contact-form/icon.jsx new file mode 100644 index 000000000000..7e06b61d5052 --- /dev/null +++ b/projects/packages/forms/src/blocks/contact-form/icon.jsx @@ -0,0 +1,24 @@ +import { Path } from '@wordpress/components'; +import renderMaterialIcon from '../shared/components/render-material-icon.jsx'; + +export const icon = renderMaterialIcon( + <> + + + + + + +); diff --git a/projects/packages/forms/src/blocks/contact-form/index.js b/projects/packages/forms/src/blocks/contact-form/index.js index 3b75e170d0e0..90dfe79bdcec 100644 --- a/projects/packages/forms/src/blocks/contact-form/index.js +++ b/projects/packages/forms/src/blocks/contact-form/index.js @@ -1,16 +1,15 @@ import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; -import { Path } from '@wordpress/components'; import { store as coreStore } from '@wordpress/core-data'; import { select } from '@wordpress/data'; import { decodeEntities } from '@wordpress/html-entities'; import { __, _x } from '@wordpress/i18n'; import './editor.scss'; -import renderMaterialIcon from '../shared/components/render-material-icon.jsx'; import { FORM_POST_TYPE } from '../shared/util/constants.js'; import defaultAttributes from './attributes.ts'; import blockMetadata from './block.json'; import deprecated from './deprecated.js'; import edit from './edit.tsx'; +import { icon } from './icon.jsx'; import transforms from './transforms.js'; import { DEFAULT_FORM_LABEL, extractTitleText, formatFormLabel } from './util/form-label.js'; import variations from './variations.js'; @@ -48,28 +47,6 @@ export const getFormLabel = ( { ref } ) => { } ); }; -export const icon = renderMaterialIcon( - <> - - - - - - -); - // Extract only valid block registration properties from block.json // Exclude file-based properties like editorScript, style, etc. const { editorScript, style, name: blockName, $schema, ...validBlockMetadata } = blockMetadata; diff --git a/projects/packages/forms/src/dashboard/forms/index.tsx b/projects/packages/forms/src/dashboard/forms/index.tsx index eab47a8be2fe..01f7e4bee918 100644 --- a/projects/packages/forms/src/dashboard/forms/index.tsx +++ b/projects/packages/forms/src/dashboard/forms/index.tsx @@ -19,7 +19,7 @@ import { useNavigate } from 'react-router'; /** * Internal dependencies */ -import { icon as formBlockIcon } from '../../blocks/contact-form/index.js'; +import { icon as formBlockIcon } from '../../blocks/contact-form/icon.jsx'; import { getEmbedCode, getShortcode } from '../../blocks/shared/util/embed-codes'; import useConfigValue from '../../hooks/use-config-value.ts'; import CreateFormButton from '../components/create-form-button/index.tsx'; From 8b20662497f6fdd224f9d63cb16da96c2ea3fb0f Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Fri, 29 May 2026 18:04:47 +0300 Subject: [PATCH 5/6] Separate regular and block icons --- projects/packages/forms/src/blocks/contact-form/icon.jsx | 7 ++++++- projects/packages/forms/src/blocks/contact-form/index.js | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/projects/packages/forms/src/blocks/contact-form/icon.jsx b/projects/packages/forms/src/blocks/contact-form/icon.jsx index 7e06b61d5052..9cfea2c4cac7 100644 --- a/projects/packages/forms/src/blocks/contact-form/icon.jsx +++ b/projects/packages/forms/src/blocks/contact-form/icon.jsx @@ -1,7 +1,7 @@ import { Path } from '@wordpress/components'; import renderMaterialIcon from '../shared/components/render-material-icon.jsx'; -export const icon = renderMaterialIcon( +const iconPaths = ( <> @@ -22,3 +22,8 @@ export const icon = renderMaterialIcon( /> ); + +export const blockIcon = renderMaterialIcon( iconPaths ); + +// Static SVG element for @wordpress/ui EmptyState (expects an element, not a component). +export const icon = blockIcon(); diff --git a/projects/packages/forms/src/blocks/contact-form/index.js b/projects/packages/forms/src/blocks/contact-form/index.js index 90dfe79bdcec..2587170af34e 100644 --- a/projects/packages/forms/src/blocks/contact-form/index.js +++ b/projects/packages/forms/src/blocks/contact-form/index.js @@ -9,7 +9,7 @@ import defaultAttributes from './attributes.ts'; import blockMetadata from './block.json'; import deprecated from './deprecated.js'; import edit from './edit.tsx'; -import { icon } from './icon.jsx'; +import { blockIcon } from './icon.jsx'; import transforms from './transforms.js'; import { DEFAULT_FORM_LABEL, extractTitleText, formatFormLabel } from './util/form-label.js'; import variations from './variations.js'; @@ -60,7 +60,7 @@ export const settings = { 'Create forms to collect data from site visitors and manage their responses.', 'jetpack-forms' ), - icon: { src: icon }, + icon: { src: blockIcon }, keywords: [ _x( 'email', 'block search term', 'jetpack-forms' ), _x( 'feedback', 'block search term', 'jetpack-forms' ), From 2ce4a7200e2f23c398dd73a643301d2966472613 Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Fri, 29 May 2026 18:06:08 +0300 Subject: [PATCH 6/6] Get rid of materialIcon() --- .../forms/src/blocks/contact-form/icon.jsx | 14 ++++---------- .../forms/src/blocks/contact-form/index.js | 4 ++-- .../form-editor/plugins/form-pre-publish-panel.tsx | 4 +--- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/projects/packages/forms/src/blocks/contact-form/icon.jsx b/projects/packages/forms/src/blocks/contact-form/icon.jsx index 9cfea2c4cac7..e21407299aa3 100644 --- a/projects/packages/forms/src/blocks/contact-form/icon.jsx +++ b/projects/packages/forms/src/blocks/contact-form/icon.jsx @@ -1,8 +1,7 @@ -import { Path } from '@wordpress/components'; -import renderMaterialIcon from '../shared/components/render-material-icon.jsx'; +import { SVG, Path } from '@wordpress/primitives'; -const iconPaths = ( - <> +export const icon = ( + - + ); - -export const blockIcon = renderMaterialIcon( iconPaths ); - -// Static SVG element for @wordpress/ui EmptyState (expects an element, not a component). -export const icon = blockIcon(); diff --git a/projects/packages/forms/src/blocks/contact-form/index.js b/projects/packages/forms/src/blocks/contact-form/index.js index 2587170af34e..90dfe79bdcec 100644 --- a/projects/packages/forms/src/blocks/contact-form/index.js +++ b/projects/packages/forms/src/blocks/contact-form/index.js @@ -9,7 +9,7 @@ import defaultAttributes from './attributes.ts'; import blockMetadata from './block.json'; import deprecated from './deprecated.js'; import edit from './edit.tsx'; -import { blockIcon } from './icon.jsx'; +import { icon } from './icon.jsx'; import transforms from './transforms.js'; import { DEFAULT_FORM_LABEL, extractTitleText, formatFormLabel } from './util/form-label.js'; import variations from './variations.js'; @@ -60,7 +60,7 @@ export const settings = { 'Create forms to collect data from site visitors and manage their responses.', 'jetpack-forms' ), - icon: { src: blockIcon }, + icon: { src: icon }, keywords: [ _x( 'email', 'block search term', 'jetpack-forms' ), _x( 'feedback', 'block search term', 'jetpack-forms' ), diff --git a/projects/packages/forms/src/form-editor/plugins/form-pre-publish-panel.tsx b/projects/packages/forms/src/form-editor/plugins/form-pre-publish-panel.tsx index 04d5188a37f5..2c7fd8289c00 100644 --- a/projects/packages/forms/src/form-editor/plugins/form-pre-publish-panel.tsx +++ b/projects/packages/forms/src/form-editor/plugins/form-pre-publish-panel.tsx @@ -277,9 +277,7 @@ export const FormPrePublishPanel = () => { return (
- - { formBlockSettings.icon.src() } - + { formBlockSettings.icon.src } { decodeEntities( postTitle ) || __( 'Untitled Form', 'jetpack-forms' ) }