refactor: use Mantine Breadcrumbs for app navigation

This commit is contained in:
2026-08-27 12:55:00 +03:00
parent d53ce50e28
commit 3c459e66cc
3 changed files with 27 additions and 33 deletions
+3 -9
View File
@@ -32,15 +32,10 @@ a {
.bottom-nav { .bottom-nav {
display: none; display: none;
} }
.breadcrumbs { [data-depth] {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.breadcrumbs-entry { [data-depth] a {
display: contents;
}
.breadcrumbs a {
color: var(--ft-color-accent); color: var(--ft-color-accent);
} }
.auth-page { .auth-page {
@@ -75,8 +70,7 @@ a {
color: var(--ft-color-accent); color: var(--ft-color-accent);
font-weight: 600; font-weight: 600;
} }
.breadcrumbs[data-depth="3"] .breadcrumbs-item-0, [data-depth="3"] > :nth-child(-n + 2) {
.breadcrumbs[data-depth="3"] .breadcrumbs-separator-1 {
display: none; display: none;
} }
.mantine-AppShell-main { .mantine-AppShell-main {
+7 -1
View File
@@ -1,3 +1,4 @@
import { MantineProvider } from "@mantine/core";
import { cleanup, render, screen } from "@testing-library/react"; import { cleanup, render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router"; import { MemoryRouter } from "react-router";
import { afterEach, describe, expect, it, vi } from "vitest"; import { afterEach, describe, expect, it, vi } from "vitest";
@@ -15,9 +16,11 @@ function renderBreadcrumbs(
) { ) {
useBrokerageAccounts.mockReturnValue({ data: accounts }); useBrokerageAccounts.mockReturnValue({ data: accounts });
return render( return render(
<MantineProvider>
<MemoryRouter initialEntries={[path]}> <MemoryRouter initialEntries={[path]}>
<AppBreadcrumbs /> <AppBreadcrumbs />
</MemoryRouter>, </MemoryRouter>
</MantineProvider>,
); );
} }
@@ -67,6 +70,9 @@ describe("AppBreadcrumbs", () => {
"page", "page",
); );
expect(screen.getByRole("navigation")).toHaveAttribute("data-depth", "3"); expect(screen.getByRole("navigation")).toHaveAttribute("data-depth", "3");
for (const separator of screen.getAllByText("→")) {
expect(separator).toHaveAttribute("aria-hidden", "true");
}
}); });
it("uses the account fallback without exposing the identifier", () => { it("uses the account fallback without exposing the identifier", () => {
+14 -20
View File
@@ -1,3 +1,4 @@
import { Breadcrumbs } from "@mantine/core";
import type { FC } from "react"; import type { FC } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useMatch } from "react-router"; import { Link, useMatch } from "react-router";
@@ -20,31 +21,24 @@ const BreadcrumbTrail: FC<BreadcrumbTrailProps> = (props) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<nav <Breadcrumbs
aria-label={t("breadcrumbs.label")} aria-label={t("breadcrumbs.label")}
className="breadcrumbs" component="nav"
data-depth={items.length} data-depth={items.length}
separator={<span aria-hidden="true">→</span>}
> >
{items.map((item, index) => ( {items.map((item) =>
<span className="breadcrumbs-entry" key={item.to ?? item.label}> item.to ? (
{index ? ( <Link key={item.to} to={item.to}>
<span {item.label}
aria-hidden="true" </Link>
className={`breadcrumbs-separator-${index}`}
>
→
</span>
) : null}
<span className={`breadcrumbs-item-${index}`}>
{item.to ? (
<Link to={item.to}>{item.label}</Link>
) : ( ) : (
<span aria-current="page">{item.label}</span> <span aria-current="page" key={item.label}>
{item.label}
</span>
),
)} )}
</span> </Breadcrumbs>
</span>
))}
</nav>
); );
}; };