diff --git a/frontend/messages/de.json b/frontend/messages/de.json
index 5fdde62b..aa020733 100644
--- a/frontend/messages/de.json
+++ b/frontend/messages/de.json
@@ -116,8 +116,8 @@
"favoritesEmptyCta": "Tippen Sie ❤️ auf einem Produkt",
"newProducts": "Neue Produkte",
"newInCategory": "Neu in {category}",
- "viewAll": "Alle anzeigen →",
- "viewHistory": "Verlauf anzeigen →",
+ "viewAll": "Alle anzeigen",
+ "viewHistory": "Verlauf anzeigen",
"browse": "Durchsuchen →",
"scanned": "Gescannt",
"viewed": "Angesehen",
diff --git a/frontend/messages/en.json b/frontend/messages/en.json
index ec25813f..6443b6c6 100644
--- a/frontend/messages/en.json
+++ b/frontend/messages/en.json
@@ -116,8 +116,8 @@
"favoritesEmptyCta": "Tap \u2764\uFE0F on any product",
"newProducts": "New Products",
"newInCategory": "New {category}",
- "viewAll": "View all →",
- "viewHistory": "View history →",
+ "viewAll": "View all",
+ "viewHistory": "View history",
"browse": "Browse →",
"scanned": "Scanned",
"viewed": "Viewed",
diff --git a/frontend/messages/pl.json b/frontend/messages/pl.json
index 424faabe..e24f93d2 100644
--- a/frontend/messages/pl.json
+++ b/frontend/messages/pl.json
@@ -116,8 +116,8 @@
"favoritesEmptyCta": "Kliknij \u2764\uFE0F przy produkcie",
"newProducts": "Nowe produkty",
"newInCategory": "Nowe {category}",
- "viewAll": "Pokaż wszystko →",
- "viewHistory": "Historia →",
+ "viewAll": "Pokaż wszystko",
+ "viewHistory": "Historia",
"browse": "Przeglądaj →",
"scanned": "Zeskanowane",
"viewed": "Przeglądane",
diff --git a/frontend/src/components/dashboard/CategoriesBrowse.test.tsx b/frontend/src/components/dashboard/CategoriesBrowse.test.tsx
index 9f090df6..91e9716c 100644
--- a/frontend/src/components/dashboard/CategoriesBrowse.test.tsx
+++ b/frontend/src/components/dashboard/CategoriesBrowse.test.tsx
@@ -146,6 +146,22 @@ describe("CategoriesBrowse", () => {
});
});
+ it("View All link includes an arrow icon (no text arrow)", async () => {
+ mockGetCategoryOverview.mockResolvedValue({
+ ok: true,
+ data: MOCK_CATEGORIES,
+ });
+ render(, { wrapper: createWrapper() });
+ await vi.waitFor(() => {
+ const viewAll = screen.getAllByRole("link").find(
+ (l) => l.getAttribute("href") === "/app/categories",
+ );
+ expect(viewAll).toBeDefined();
+ expect(viewAll!.querySelector("svg")).toBeInTheDocument();
+ expect(viewAll!.textContent).not.toContain("\u2192");
+ });
+ });
+
it("renders category icons for each chip", async () => {
mockGetCategoryOverview.mockResolvedValue({
ok: true,
diff --git a/frontend/src/components/dashboard/CategoriesBrowse.tsx b/frontend/src/components/dashboard/CategoriesBrowse.tsx
index c878d35a..7c4d9261 100644
--- a/frontend/src/components/dashboard/CategoriesBrowse.tsx
+++ b/frontend/src/components/dashboard/CategoriesBrowse.tsx
@@ -10,6 +10,7 @@ import { queryKeys, staleTimes } from "@/lib/query-keys";
import { createClient } from "@/lib/supabase/client";
import type { CategoryOverviewItem } from "@/lib/types";
import { useQuery } from "@tanstack/react-query";
+import { ArrowRight } from "lucide-react";
import Link from "next/link";
function CategoryChip({
@@ -68,9 +69,10 @@ export function CategoriesBrowse() {
{t("dashboard.viewAll")}
+
diff --git a/frontend/src/components/dashboard/NutritionTip.test.tsx b/frontend/src/components/dashboard/NutritionTip.test.tsx
index beac3a58..b7dde662 100644
--- a/frontend/src/components/dashboard/NutritionTip.test.tsx
+++ b/frontend/src/components/dashboard/NutritionTip.test.tsx
@@ -1,5 +1,5 @@
-import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
import { NutritionTip } from "./NutritionTip";
// ─── Mocks ──────────────────────────────────────────────────────────────────
@@ -52,6 +52,13 @@ describe("NutritionTip", () => {
expect(link.getAttribute("href")).toMatch(/^\/learn\//);
});
+ it("learn more link uses icon arrow instead of text arrow", () => {
+ render();
+ const link = screen.getByText(/Learn more/);
+ expect(link.querySelector("svg")).toBeInTheDocument();
+ expect(link.textContent).not.toContain("\u2192");
+ });
+
it("learn more link points to a valid learn path", () => {
render();
const link = screen.getByText(/Learn more/);
diff --git a/frontend/src/components/dashboard/NutritionTip.tsx b/frontend/src/components/dashboard/NutritionTip.tsx
index 0cffada3..52c57968 100644
--- a/frontend/src/components/dashboard/NutritionTip.tsx
+++ b/frontend/src/components/dashboard/NutritionTip.tsx
@@ -2,9 +2,10 @@
// ─── NutritionTip — cycling daily health tip card ───────────────────────────
-import Link from "next/link";
import { useTranslation } from "@/lib/i18n";
import { qaStable } from "@/lib/qa-mode";
+import { ArrowRight } from "lucide-react";
+import Link from "next/link";
/** Total number of tips available in i18n files (dashboard.tip.0 … tip.N-1). */
const TIP_COUNT = 14;
@@ -67,9 +68,10 @@ export function NutritionTip() {
{learnHref && (
- {t("dashboard.tipLearnMore")} →
+ {t("dashboard.tipLearnMore")}
+
)}
diff --git a/frontend/src/components/dashboard/RecentlyViewed.test.tsx b/frontend/src/components/dashboard/RecentlyViewed.test.tsx
index 1277774e..be8b9609 100644
--- a/frontend/src/components/dashboard/RecentlyViewed.test.tsx
+++ b/frontend/src/components/dashboard/RecentlyViewed.test.tsx
@@ -11,7 +11,7 @@ vi.mock("@/lib/i18n", () => ({
const map: Record = {
"dashboard.recentlyViewedCompact": "Recently Viewed",
"dashboard.viewAll": "View all",
- "dashboard.viewHistory": "View history →",
+ "dashboard.viewHistory": "View history",
};
return map[key] ?? key;
},
@@ -133,6 +133,15 @@ describe("RecentlyViewed", () => {
expect(link).toHaveAttribute("href", "/app/search");
});
+ it("renders a single arrow icon in View history link (no text arrow)", () => {
+ const products = [makeProduct(1)];
+ render();
+
+ const link = screen.getByRole("link", { name: /View history/ });
+ expect(link.querySelector("svg")).toBeInTheDocument();
+ expect(link.textContent).not.toContain("\u2192");
+ });
+
it("has section aria-label", () => {
const products = [makeProduct(1)];
render();