diff --git a/frontend/src/app/board-groups/[groupId]/page.tsx b/frontend/src/app/board-groups/[groupId]/page.tsx
index e2325fe4..56a3d3c4 100644
--- a/frontend/src/app/board-groups/[groupId]/page.tsx
+++ b/frontend/src/app/board-groups/[groupId]/page.tsx
@@ -744,7 +744,7 @@ export default function BoardGroupDetailPage() {
-
+
@@ -816,7 +816,7 @@ export default function BoardGroupDetailPage() {
-
+
-
+
{heartbeatApplyError ? (
diff --git a/frontend/src/app/boards/[boardId]/approvals/page.tsx b/frontend/src/app/boards/[boardId]/approvals/page.tsx
index 531ca138..0a2fb8c4 100644
--- a/frontend/src/app/boards/[boardId]/approvals/page.tsx
+++ b/frontend/src/app/boards/[boardId]/approvals/page.tsx
@@ -33,9 +33,9 @@ export default function BoardApprovalsPage() {
-
+
{boardId ? (
-
+
) : null}
diff --git a/frontend/src/app/boards/[boardId]/page.tsx b/frontend/src/app/boards/[boardId]/page.tsx
index ccb7358a..a30c4078 100644
--- a/frontend/src/app/boards/[boardId]/page.tsx
+++ b/frontend/src/app/boards/[boardId]/page.tsx
@@ -3101,7 +3101,7 @@ export default function BoardDetailPage() {
)}
>
-
+
@@ -3237,9 +3237,9 @@ export default function BoardDetailPage() {
-
+
{isOrgAdmin ? (
-
+
@@ -3680,12 +3680,12 @@ export default function BoardDetailPage() {
) : null}
-
+
Task detail
@@ -3749,7 +3749,7 @@ export default function BoardDetailPage() {
return (
{definition.label || definition.field_key}
@@ -3993,12 +3993,12 @@ export default function BoardDetailPage() {
-
+
Board chat
@@ -4055,12 +4055,12 @@ export default function BoardDetailPage() {
-
+
Live feed
diff --git a/frontend/src/app/dashboard/page.tsx b/frontend/src/app/dashboard/page.tsx
index 7fbc3649..de72b898 100644
--- a/frontend/src/app/dashboard/page.tsx
+++ b/frontend/src/app/dashboard/page.tsx
@@ -379,7 +379,7 @@ function TopMetricCard({
: "bg-green-50 text-green-600";
return (
-
+
@@ -423,7 +423,7 @@ function InfoBlock({
rows: SummaryRow[];
}) {
return (
-
+
{title}
@@ -513,6 +513,8 @@ export default function DashboardPage() {
enabled: Boolean(isSignedIn),
refetchInterval: 15_000,
refetchOnMount: "always",
+ retry: 3,
+ retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 5000),
},
},
);
@@ -899,10 +901,10 @@ export default function DashboardPage() {
-
+
{metricsQuery.error ? (
- {metricsQuery.error.message}
+ Load failed: {metricsQuery.error.message}
) : null}
@@ -958,7 +960,7 @@ export default function DashboardPage() {
/>
-
+
Pending Approvals
-
+
Sessions
{formatCount(activeSessions)}
@@ -1082,7 +1084,7 @@ export default function DashboardPage() {
-
+
Recent Activity
-
+
Organization Invite
@@ -158,7 +158,7 @@ export default function InvitePage() {
-
+
diff --git a/frontend/src/app/organization/page.tsx b/frontend/src/app/organization/page.tsx
index 23e2e420..d4de3c27 100644
--- a/frontend/src/app/organization/page.tsx
+++ b/frontend/src/app/organization/page.tsx
@@ -704,7 +704,7 @@ export default function OrganizationPage() {
-
+
@@ -775,7 +775,7 @@ export default function OrganizationPage() {
-
+
diff --git a/frontend/src/components/auth/SignedOutPanel.tsx b/frontend/src/components/auth/SignedOutPanel.tsx
index 222dad08..e1c92264 100644
--- a/frontend/src/components/auth/SignedOutPanel.tsx
+++ b/frontend/src/components/auth/SignedOutPanel.tsx
@@ -21,7 +21,7 @@ export function SignedOutPanel({
}: SignedOutPanelProps) {
return (
-
+
{message}
+
Navigation
diff --git a/frontend/src/components/tables/DataTable.tsx b/frontend/src/components/tables/DataTable.tsx
index 8685f798..c03d5747 100644
--- a/frontend/src/components/tables/DataTable.tsx
+++ b/frontend/src/components/tables/DataTable.tsx
@@ -59,10 +59,10 @@ export function DataTable({
stickyHeader = false,
tableClassName = "w-full text-left text-sm",
headerClassName,
- headerCellClassName = "px-6 py-3",
+ headerCellClassName = "px-3 py-2 md:px-6 md:py-3",
bodyClassName = "divide-y divide-slate-100",
rowClassName = "hover:bg-slate-50",
- cellClassName = "px-6 py-4",
+ cellClassName = "px-3 py-3 md:px-6 md:py-4",
}: DataTableProps) {
const resolvedRowActions = rowActions
? (rowActions.actions ??
diff --git a/frontend/src/components/templates/DashboardPageLayout.tsx b/frontend/src/components/templates/DashboardPageLayout.tsx
index e29a937e..1485cbc7 100644
--- a/frontend/src/components/templates/DashboardPageLayout.tsx
+++ b/frontend/src/components/templates/DashboardPageLayout.tsx
@@ -75,7 +75,7 @@ export function DashboardPageLayout({
headerClassName,
)}
>
-
+
{headerActions ? (
@@ -103,7 +103,7 @@ export function DashboardPageLayout({
-
+
{showAdminOnlyNotice ? (
) : (
diff --git a/frontend/src/components/templates/DashboardShell.tsx b/frontend/src/components/templates/DashboardShell.tsx
index e3cb3071..ec979b6e 100644
--- a/frontend/src/components/templates/DashboardShell.tsx
+++ b/frontend/src/components/templates/DashboardShell.tsx
@@ -1,8 +1,9 @@
"use client";
-import { useEffect } from "react";
+import { useCallback, useEffect, useState } from "react";
import type { ReactNode } from "react";
import { usePathname, useRouter } from "next/navigation";
+import { Menu, X } from "lucide-react";
import { SignedIn, useAuth } from "@/auth/clerk";
@@ -21,6 +22,7 @@ export function DashboardShell({ children }: { children: ReactNode }) {
const pathname = usePathname();
const { isSignedIn } = useAuth();
const isOnboardingPath = pathname === "/onboarding";
+ const [sidebarOpen, setSidebarOpen] = useState(false);
const meQuery = useGetMeApiV1UsersMeGet<
getMeApiV1UsersMeGetResponse,
@@ -36,6 +38,11 @@ export function DashboardShell({ children }: { children: ReactNode }) {
const displayName = profile?.name ?? profile?.preferred_name ?? "Operator";
const displayEmail = profile?.email ?? "";
+ // Close sidebar on navigation
+ useEffect(() => {
+ setSidebarOpen(false);
+ }, [pathname]);
+
useEffect(() => {
if (!isSignedIn || isOnboardingPath) return;
if (!profile) return;
@@ -68,22 +75,32 @@ export function DashboardShell({ children }: { children: ReactNode }) {
};
}, []);
+ const toggleSidebar = useCallback(() => setSidebarOpen((v) => !v), []);
+
return (
-
+
-
-
+
+
+
+ {sidebarOpen ? : }
+
-
+
-
+
{displayName}
@@ -95,7 +112,20 @@ export function DashboardShell({ children }: { children: ReactNode }) {
-
+
+ {/* Mobile sidebar overlay */}
+ {sidebarOpen ? (
+
e.key === "Escape" && toggleSidebar()}
+ role="button"
+ tabIndex={-1}
+ aria-label="Close navigation"
+ />
+ ) : null}
+
+
{children}