Skip to content

Commit

Permalink
Merge pull request #259 from heorhi-deriv/FEQ-2683-Implement-Breadcru…
Browse files Browse the repository at this point in the history
…mbs-Component

[FEQ] george / FEQ-2683 / Implement Breadcrumbs Component
  • Loading branch information
shayan-deriv authored Oct 3, 2024
2 parents dcf7793 + 37b98e9 commit 1b6334b
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 1 deletion.
38 changes: 38 additions & 0 deletions src/components/Breadcrumbs/Breadcrumbs.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.deriv-breadcrumbs {
margin: 0;
padding: 0;

&__item {
float: left;
list-style-type: none;
}

&__text {
color: var(--du-text-less-prominent, #999999);

&--active {
color: var(--du-text-prominent, #333333);
}

&:not(:last-child) {
cursor: pointer;

&:hover {
color: var(--du-text-general, #333333);
}
}
}

&__chevron-icon {
margin: 0 5px;
vertical-align: middle;

path {
fill: var(--du-text-less-prominent, #999999);
}

@include mobile {
margin: 0 2.5px;
}
}
}
54 changes: 54 additions & 0 deletions src/components/Breadcrumbs/__tests__/Breadcrumbs.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from "react";
import { render, screen, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Breadcrumbs } from "..";

const items = [
{ value: 0, text: "Item1" },
{ value: 1, text: "Item2" },
{ value: 2, text: "Item3" },
{ value: 3, text: "Item4" },
];

describe("Breadcrumb component", () => {
it("renders all provided items", () => {
const handleOnClick = jest.fn();
render(<Breadcrumbs items={items} handleOnClick={handleOnClick} />);

const list = screen.getByRole("list");
const { getAllByRole } = within(list);
const renderedBreadCrumbs = getAllByRole("listitem");

expect(renderedBreadCrumbs.length).toBe(4);
});

it("triggers provided callback when item was clicked", async () => {
const handleOnClick = jest.fn();
render(<Breadcrumbs items={items} handleOnClick={handleOnClick} />);

const list = screen.getByRole("list");
const { getByText } = within(list);
userEvent.click(getByText("Item1"));

await waitFor(() => {
expect(handleOnClick).toHaveBeenCalledTimes(1);
});
});

it("renders all provided items with custom separator ", () => {
const handleOnClick = jest.fn();
render(
<Breadcrumbs
items={items}
handleOnClick={handleOnClick}
separator={<div data-testid="dt_separator">{`-->`}</div>}
/>,
);

const list = screen.getByRole("list");
const { getAllByTestId } = within(list);
const renderedSeparators = getAllByTestId("dt_separator");

expect(renderedSeparators.length).toBe(3);
});
});
58 changes: 58 additions & 0 deletions src/components/Breadcrumbs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { ComponentProps, ReactNode } from "react";
import clsx from "clsx";
import { LegacyChevronRight1pxIcon } from "@deriv/quill-icons";
import { Text } from "../Text";
import "./Breadcrumbs.scss";

type TItem = {
value?: string | number;
text: string | JSX.Element;
};

type BreadcrumbsProps = {
className?: string;
items: TItem[];
handleOnClick: (item: TItem) => void;
separator?: ReactNode;
textSize?: ComponentProps<typeof Text>["size"];
};

export const Breadcrumbs = ({
className,
items,
handleOnClick,
separator,
textSize = "sm",
}: BreadcrumbsProps) => {
return (
<ul className={clsx("deriv-breadcrumbs", className)}>
{items.map((item: TItem, idx: number) => {
const isLastItem = idx === items.length - 1;

return (
<li
key={item.value ?? idx}
className="deriv-breadcrumbs__item"
>
<Text
className={clsx("deriv-breadcrumbs__text", {
"deriv-breadcrumbs__text--active": isLastItem,
})}
size={textSize}
onClick={() => handleOnClick(item)}
>
{item.text}
</Text>
{!isLastItem &&
(separator ?? (
<LegacyChevronRight1pxIcon
className="deriv-breadcrumbs__chevron-icon"
iconSize="xs"
/>
))}
</li>
);
})}
</ul>
);
};
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { Accordion } from "./components/Accordion";
export { ActionScreen } from "./components/ActionScreen";
export { Button } from "./components/Button";
export { Badge } from "./components/Badge";
export { Breadcrumbs } from "./components/Breadcrumbs";
export { Checkbox } from "./components/Checkbox";
export { CircularProgressBar } from "./components/CircularProgressBar";
export { Divider } from "./components/Divider";
Expand Down
2 changes: 2 additions & 0 deletions src/styles/base/_root.scss
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
--du-general-section-6: #{$color-gray-2};
--du-general-disabled: #{$color-gray-3};
--du-general-hover: #{$color-gray-4};
--du-general-hover-1: #{$color-black-1};
--du-general-active: #{$color-gray-5};
// Icons and Texts
--du-text-general: #{$color-black-1};
Expand Down Expand Up @@ -250,6 +251,7 @@
--du-general-section-6: #{$color-gray-7};
--du-general-disabled: #{$color-black-4};
--du-general-hover: #{$color-black-5};
--du-general-hover-1: #{$color-white};
--du-general-active: #{$color-black-8};
// Icons and Texts
--du-text-prominent: #{$color-white};
Expand Down
2 changes: 1 addition & 1 deletion stories/Badge.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const meta = {
args: {
variant: "contained",
children: "label",
color: "lightblue",
color: "light-blue",
badgeSize: "md",
isBold: true,
rightIcon: <span>👉</span>,
Expand Down
31 changes: 31 additions & 0 deletions stories/Breadcrumbs.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Meta, StoryObj } from "@storybook/react";
import { Breadcrumbs } from "../src/components/Breadcrumbs";
import { fn } from "@storybook/test";

const meta = {
title: "Components/Breadcrumbs",
component: Breadcrumbs,
parameters: {
layout: "centered",
},
args: {
textSize: "sm",
},
tags: ["autodocs"],
} satisfies Meta<typeof Breadcrumbs>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
name: "Default Breadcrumbs",
args: {
items: [
{ value: "Item1", text: "Item1" },
{ value: "Item2", text: "Item2" },
{ value: "Item3", text: "Item3" },
{ value: "Item4", text: "Item4" },
],
handleOnClick: fn(),
},
};

0 comments on commit 1b6334b

Please sign in to comment.