Add `Breadcrumbs` component(s)
- Dominant language
- TypeScript
- Stars
- 247
- Forks
- 78
- Avg merge
- 14h 27m
- Merged PRs (30d)
- 15
Description
## Description
Right now, we have a custom implementation of breadcrumbs. It is used to display tree-structured data in a more compact way (see screenshot below).

In our case, all the items are not clickable, but in usual cases (links to application pages) they are, so if you decide to implement that, it would be great to support both cases.
Looks like `LinkButton` is the best candidate for individual breadcrumbs. If so, it will be necessary to only implement the wrapper.
The wrapper, `Breadcrumbs` component, would do two stylistic things:
* Add forward slash between the elements
* Render the last and the rest elements differently
## Describe the solution you'd like
* Add `Breadcrumbs` wrapper component
* Add `Breadcrumb` component (or provide example, where already existing components can be used instead, like `LinkButton`)
* Decide, how the breadcrumbs should be passed to `Breadcrumbs` component. `MainMenu` approach looks the most suitable (array of objects with `render` function)
* Add documentation for the component(s)
Crude implementation example:
```typescript
import {
type LinkButton,
Text,
} from "@epam/loveship";
import {
type ComponentProps,
type FC,
Fragment,
} from "react";
type LinkButtonProps = ComponentProps;
// Or `Partial`.
type BreadcrumProps = Pick<
LinkButtonProps,
| "color"
| "size"
>;
interface BreadcrumbInfo {
id: string;
render: FC;
}
interface BreadcrumbsProps {
size?: LinkButtonProps["size"];
items: Array;
}
const Breadcrumbs: FC = ({
size,
items,
}) => {
return (
<>
{
items.map((item, index) => {
const isLast = index === items.length - 1;
const {
id,
// Allows to use hooks if rendered and not just called as a regular function (see usage below).
render: Breadcrumb,
} = item;
return (
{
!isLast
? (
{" / "}
)
: null
}
);
})
}
);
};
```
Usage example:
```typescript
import {
Breadcrumbs,
LinkButton,
} from "@epam/loveship";
const Example: FC = () => {
return (
{
return (
);
},
},
{
id: "projects",
render: (props) => {
return (
);
},
},
{
id: "project",
render: (props) => {
return (
);
},
},
]}
/>
);
};
export {
Example,
};
```
Also, if it will be necessary to filter props before passing them to render (for example, not passing `link` and `onClick` to the last element, or changing color depending on their presence), it would make sense to require passing them to the `BreadcrumbInfo` object, like this:
```typescript
import {
type LinkButton,
} from "@epam/loveship";
import {
type ComponentProps,
} from "react";
type LinkButtonProps = ComponentProps;
// Option 1.
interface BreadcrumbInfo extends LinkButtonProps {
id: string;
render: LinkButton;
}
// Option 2.
interface BreadcrumbInfo {
id: string;
props: LinkButtonProps,
render: LinkButton;
}
// Usage.
```
And to avoid typing `render: LinkButton` all the time, `render` property can be defined as optional, and `LinkButton` can be used as a default value, if the property is absent.
Contributor guide
Assessment
This issue has not been assessed yet.