Skip to content

Commit

Permalink
feat(@clayui/core): moves Breadcrumb implementation to package
Browse files Browse the repository at this point in the history
  • Loading branch information
matuzalemsteles committed Mar 14, 2024
1 parent d962263 commit 29b0b73
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 0 deletions.
136 changes: 136 additions & 0 deletions packages/clay-core/src/breadcrumb/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* SPDX-FileCopyrightText: © 2019 Liferay, Inc. <https://liferay.com>
* SPDX-License-Identifier: BSD-3-Clause
*/

import {ClayButtonWithIcon} from '@clayui/button';
import classNames from 'classnames';
import React, {useState} from 'react';
import warning from 'warning';

import {Item} from './Item';

type TItem = React.ComponentProps<typeof Item>;
type TItems = Array<TItem>;

export type Props = React.HTMLAttributes<HTMLOListElement> & {
/**
* Defines the aria label of component elements.
*/
ariaLabels?: {
breadcrumb: string;
open: string;
close: string;
};

/**
* The number of Breadcrumb Items to show on each side of the active Breadcrumb Item before
* using an ellipsis dropdown.
* @deprecated since v3.91.0 - It is no longer necessary.
*/
ellipsisBuffer?: number;

/**
* Use this property for defining `otherProps` that will be passed to ellipsis dropdown trigger.
* @deprecated since v3.91.0 - It is no longer necessary.
*/
ellipsisProps?: Object;

/**
* Property to define Breadcrumb's items.
*/
items: TItems;

/**
* Path to the location of the spritemap resource.
*/
spritemap?: string;
};

const findActiveItems = (items: TItems) => {
return items.filter((item) => {
return item.active;
});
};

export const Breadcrumb = ({
ariaLabels = {
breadcrumb: 'Breadcrumb',
close: 'Partially nest breadcrumbs',
open: 'See full nested',
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ellipsisBuffer = 1,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ellipsisProps = {},
className,
items,
spritemap,
...otherProps
}: Props) => {
warning(
findActiveItems(items).length === 1,
'ClayBreadcrumb expects at least one `active` item on `items`.'
);

const [collapsed, setCollapsed] = useState(false);

return (
<nav
aria-label={ariaLabels.breadcrumb}
className="align-items-center d-flex"
>
{items.length > 3 && (
<ClayButtonWithIcon
aria-expanded={collapsed}
aria-label={collapsed ? ariaLabels.close : ariaLabels.open}
className="breadcrumb-toggle"
displayType={null}
onClick={() => setCollapsed(!collapsed)}
size="xs"
spritemap={spritemap}
symbol={
collapsed ? 'angle-double-left' : 'angle-double-right'
}
title={collapsed ? ariaLabels.close : ariaLabels.open}
/>
)}
<ol {...otherProps} className={classNames('breadcrumb', className)}>
{items.length > 3 && !collapsed ? (
<Items
items={[
items[items.length - 2]!,
items[items.length - 1]!,
]}
/>
) : (
<Items items={items} />
)}
</ol>
</nav>
);
};

type ItemsProps = {
items: TItems;
};

function Items({items}: ItemsProps) {
return (
<>
{items.map((item: TItem | React.ReactNode, i: number) =>
React.isValidElement(item) ? (
React.cloneElement(item, {key: `ellipsis${i}`})
) : (
<Item
active={(item as TItem).active}
href={(item as TItem).href}
key={`breadcrumbItem${i}`}
label={(item as TItem).label}
onClick={(item as TItem).onClick}
/>
)
)}
</>
);
}
54 changes: 54 additions & 0 deletions packages/clay-core/src/breadcrumb/Item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* SPDX-FileCopyrightText: © 2019 Liferay, Inc. <https://liferay.com>
* SPDX-License-Identifier: BSD-3-Clause
*/

import Link from '@clayui/link';
import classNames from 'classnames';
import React from 'react';

type Props = React.HTMLAttributes<HTMLLIElement> & {
/**
* Flag to indicate if the Breadcrumb item is active or not.
*/
active?: boolean;

/**
* This value is used to be the target of the link.
*/
href?: string;

/**
* Label of the Breadcrumb item
*/
label: string;

/**
* Callback for when a Breadcrumb item is clicked.
*/
onClick?: (event: React.SyntheticEvent) => void;
};

export const Item = ({active, href, label, onClick, ...otherProps}: Props) => (
<li
className={classNames('breadcrumb-item', {
active,
})}
{...otherProps}
>
<Link
aria-current={active ? 'page' : undefined}
className="breadcrumb-link"
data-testid={`testId${label}`}
href={active ? '#' : href}
onClick={(event) => {
if (onClick) {
event.preventDefault();
onClick(event);
}
}}
>
{label}
</Link>
</li>
);
6 changes: 6 additions & 0 deletions packages/clay-core/src/breadcrumb/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* SPDX-FileCopyrightText: © 2024 Liferay, Inc. <https://liferay.com>
* SPDX-License-Identifier: BSD-3-Clause
*/

export * from './Breadcrumb';
1 change: 1 addition & 0 deletions packages/clay-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export {Provider, useProvider} from '@clayui/provider';

export {Alert} from './alert';
export {Badge} from './badge';
export {Breadcrumb} from './breadcrumb';
export {Heading, Text, TextHighlight} from './typography';
export {OverlayMask} from './overlay-mask';
export {TreeView} from './tree-view';
Expand Down

0 comments on commit 29b0b73

Please sign in to comment.