From b2f66e3cf40d03eb887b194f7661407249fdaaeb Mon Sep 17 00:00:00 2001 From: Joshua T Flowers Date: Fri, 18 Nov 2022 09:51:01 -0800 Subject: [PATCH] Add breadcrumbs to new product management experience (#35596) * Add product breadcrumbs component * Add breadcrumb styling * Truncate breadcrumbs when more than 3 * Add tests around product breadcrumbs * Add changelog entry * Convert indentation to tabs * Add key to mapped breadcrumb items --- .../client/products/product-breadcrumbs.scss | 24 ++++++ .../client/products/product-breadcrumbs.tsx | 58 ++++++++++++++ .../client/products/product-title.tsx | 9 +++ .../test/product-breadcrumbs.spec.tsx | 75 +++++++++++++++++++ plugins/woocommerce/changelog/add-35170 | 4 + 5 files changed, 170 insertions(+) create mode 100644 plugins/woocommerce-admin/client/products/product-breadcrumbs.scss create mode 100644 plugins/woocommerce-admin/client/products/product-breadcrumbs.tsx create mode 100644 plugins/woocommerce-admin/client/products/test/product-breadcrumbs.spec.tsx create mode 100644 plugins/woocommerce/changelog/add-35170 diff --git a/plugins/woocommerce-admin/client/products/product-breadcrumbs.scss b/plugins/woocommerce-admin/client/products/product-breadcrumbs.scss new file mode 100644 index 00000000000..ef81f4ca6bc --- /dev/null +++ b/plugins/woocommerce-admin/client/products/product-breadcrumbs.scss @@ -0,0 +1,24 @@ +.woocommerce-product-breadcrumbs { + display: flex; + align-items: center; +} + +.woocommerce-product-breadcrumbs__item { + font-weight: 400; + color: $gray-700; + + a { + color: $gray-700; + text-decoration: none; + &:hover { + text-decoration: underline; + } + } +} + +.woocommerce-product-breadcrumbs__separator { + display: inline-flex; + path { + fill: $gray-700; + } +} diff --git a/plugins/woocommerce-admin/client/products/product-breadcrumbs.tsx b/plugins/woocommerce-admin/client/products/product-breadcrumbs.tsx new file mode 100644 index 00000000000..e69e412e8e8 --- /dev/null +++ b/plugins/woocommerce-admin/client/products/product-breadcrumbs.tsx @@ -0,0 +1,58 @@ +/** + * External dependencies + */ +import { chevronRightSmall, Icon } from '@wordpress/icons'; +import { Fragment } from '@wordpress/element'; +import { Link } from '@woocommerce/components'; + +/** + * Internal dependencies + */ +import './product-breadcrumbs.scss'; + +type Breadcrumb = { + href?: string; + title: string | JSX.Element; + type?: 'wp-admin' | 'wc-admin'; +}; + +export const ProductBreadcrumbs = ( { + breadcrumbs, +}: { + breadcrumbs: Breadcrumb[]; +} ) => { + const visibleBreadcrumbs = + breadcrumbs.length > 3 + ? [ + breadcrumbs[ 0 ], + { + title: <>…, + }, + breadcrumbs[ breadcrumbs.length - 1 ], + ] + : breadcrumbs; + + return ( + + { visibleBreadcrumbs.map( ( breadcrumb ) => { + const { href, title, type } = breadcrumb; + return ( + + + { href ? ( + + { title } + + ) : ( + title + ) } + + + + + + ); + } ) } + + ); +}; diff --git a/plugins/woocommerce-admin/client/products/product-title.tsx b/plugins/woocommerce-admin/client/products/product-title.tsx index 31f54719e6e..b1e438091d3 100644 --- a/plugins/woocommerce-admin/client/products/product-title.tsx +++ b/plugins/woocommerce-admin/client/products/product-title.tsx @@ -2,6 +2,7 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; +import { getAdminLink } from '@woocommerce/settings'; import { Product, PRODUCTS_STORE_NAME, @@ -15,6 +16,7 @@ import { useSelect } from '@wordpress/data'; * Internal dependencies */ import { getProductTitle } from './utils/get-product-title'; +import { ProductBreadcrumbs } from './product-breadcrumbs'; import { ProductStatusBadge } from './product-status-badge'; import { WooHeaderPageTitle } from '~/header/utils'; @@ -34,10 +36,17 @@ export const ProductTitle: React.FC = () => { }; } ); + const breadcrumbs = [ + { + href: getAdminLink( 'edit.php?post_type=product' ), + title: __( 'Products', 'woocommerce' ), + }, + ]; const title = getProductTitle( values.name, values.type, persistedName ); return ( + { title } diff --git a/plugins/woocommerce-admin/client/products/test/product-breadcrumbs.spec.tsx b/plugins/woocommerce-admin/client/products/test/product-breadcrumbs.spec.tsx new file mode 100644 index 00000000000..52b14504227 --- /dev/null +++ b/plugins/woocommerce-admin/client/products/test/product-breadcrumbs.spec.tsx @@ -0,0 +1,75 @@ +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + +/** + * Internal dependencies + */ +import { ProductBreadcrumbs } from '../product-breadcrumbs'; + +describe( 'ProductBreadcrumbs', () => { + it( 'should render a breadcrumb', () => { + const { getByText } = render( + + ); + const breadcrumb = getByText( 'Test breadcrumb' ) as HTMLAnchorElement; + expect( breadcrumb ).toBeInTheDocument(); + expect( breadcrumb.href ).toBe( 'http://localhost/test-url' ); + } ); + + it( 'should render multiple breadcrumbs', () => { + const { getByText } = render( + + ); + expect( getByText( 'Breadcrumb 1' ) ).toBeInTheDocument(); + expect( getByText( 'Breadcrumb 2' ) ).toBeInTheDocument(); + } ); + + it( 'should truncate breadcrumbs when more than 3 exist', () => { + const { getByText, queryByText } = render( + + ); + expect( getByText( 'Breadcrumb 1' ) ).toBeInTheDocument(); + expect( queryByText( 'Breadcrumb 2' ) ).not.toBeInTheDocument(); + expect( queryByText( 'Breadcrumb 3' ) ).not.toBeInTheDocument(); + expect( getByText( 'Breadcrumb 4' ) ).toBeInTheDocument(); + } ); +} ); diff --git a/plugins/woocommerce/changelog/add-35170 b/plugins/woocommerce/changelog/add-35170 new file mode 100644 index 00000000000..afe44ce2293 --- /dev/null +++ b/plugins/woocommerce/changelog/add-35170 @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add new product management breadcrumbs to header