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
This commit is contained in:
parent
6d4c1b3b8a
commit
b2f66e3cf4
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<span className="woocommerce-product-breadcrumbs">
|
||||
{ visibleBreadcrumbs.map( ( breadcrumb ) => {
|
||||
const { href, title, type } = breadcrumb;
|
||||
return (
|
||||
<Fragment key={ href }>
|
||||
<span className="woocommerce-product-breadcrumbs__item">
|
||||
{ href ? (
|
||||
<Link href={ href } type={ type || 'wp-admin' }>
|
||||
{ title }
|
||||
</Link>
|
||||
) : (
|
||||
title
|
||||
) }
|
||||
</span>
|
||||
<span className="woocommerce-product-breadcrumbs__separator">
|
||||
<Icon icon={ chevronRightSmall } />
|
||||
</span>
|
||||
</Fragment>
|
||||
);
|
||||
} ) }
|
||||
</span>
|
||||
);
|
||||
};
|
|
@ -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 (
|
||||
<WooHeaderPageTitle>
|
||||
<ProductBreadcrumbs breadcrumbs={ breadcrumbs } />
|
||||
{ title }
|
||||
<ProductStatusBadge />
|
||||
</WooHeaderPageTitle>
|
||||
|
|
|
@ -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(
|
||||
<ProductBreadcrumbs
|
||||
breadcrumbs={ [
|
||||
{
|
||||
href: '/test-url',
|
||||
title: 'Test breadcrumb',
|
||||
},
|
||||
] }
|
||||
/>
|
||||
);
|
||||
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(
|
||||
<ProductBreadcrumbs
|
||||
breadcrumbs={ [
|
||||
{
|
||||
href: '/test-url',
|
||||
title: 'Breadcrumb 1',
|
||||
},
|
||||
{
|
||||
href: '/test-url',
|
||||
title: 'Breadcrumb 2',
|
||||
},
|
||||
] }
|
||||
/>
|
||||
);
|
||||
expect( getByText( 'Breadcrumb 1' ) ).toBeInTheDocument();
|
||||
expect( getByText( 'Breadcrumb 2' ) ).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should truncate breadcrumbs when more than 3 exist', () => {
|
||||
const { getByText, queryByText } = render(
|
||||
<ProductBreadcrumbs
|
||||
breadcrumbs={ [
|
||||
{
|
||||
href: '/test-url',
|
||||
title: 'Breadcrumb 1',
|
||||
},
|
||||
{
|
||||
href: '/test-url',
|
||||
title: 'Breadcrumb 2',
|
||||
},
|
||||
{
|
||||
href: '/test-url',
|
||||
title: 'Breadcrumb 3',
|
||||
},
|
||||
{
|
||||
href: '/test-url',
|
||||
title: 'Breadcrumb 4',
|
||||
},
|
||||
] }
|
||||
/>
|
||||
);
|
||||
expect( getByText( 'Breadcrumb 1' ) ).toBeInTheDocument();
|
||||
expect( queryByText( 'Breadcrumb 2' ) ).not.toBeInTheDocument();
|
||||
expect( queryByText( 'Breadcrumb 3' ) ).not.toBeInTheDocument();
|
||||
expect( getByText( 'Breadcrumb 4' ) ).toBeInTheDocument();
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add new product management breadcrumbs to header
|
Loading…
Reference in New Issue