feat: refine mobile dashboard experience

This commit is contained in:
ajnart committed 2026-08-13 19:55:11 +02:00
1 parent 2e3dca3e87
commit 84db2f9d49
68 files changed
+1425 -1311

No files matched your search

@@ -38,7 +38,6 @@ export const createBoardContentPage = <TParams extends Record<string, unknown>>(
headerActions: <BoardContentHeaderActions demoReadOnly={env.DEMO_MODE && env.DEMO_READ_ONLY} />,
getInitialBoardAsync: getInitialBoard,
withTour: true,
mobileProfileInActions: true,
}),
// eslint-disable-next-line no-restricted-syntax
page: async ({ params }: { params: Promise<TParams> }) => {
@@ -0,0 +1,17 @@
import { describe, expect, test } from "vitest";
import { shouldPrefetchWidgetForRequest } from "./_prefetch-policy";
describe("shouldPrefetchWidgetForRequest", () => {
test.each(["mobile", "tablet"])("defers downloads for %s requests", (deviceType) => {
expect(shouldPrefetchWidgetForRequest("downloads", deviceType)).toBe(false);
});
test("keeps downloads prefetched for desktop requests", () => {
expect(shouldPrefetchWidgetForRequest("downloads", undefined)).toBe(true);
});
test.each(["app", "bookmarks"] as const)("keeps eager %s data prefetched on mobile", (kind) => {
expect(shouldPrefetchWidgetForRequest(kind, "mobile")).toBe(true);
});
});
@@ -0,0 +1,7 @@
import type { WidgetKind } from "@homarr/definitions";
export const shouldPrefetchWidgetForRequest = (kind: WidgetKind, deviceType: string | undefined) => {
const isMobileDevice = deviceType === "mobile" || deviceType === "tablet";
return kind !== "downloads" || !isMobileDevice;
};
@@ -8,12 +8,22 @@ import { useRequiredBoard } from "@homarr/boards/context";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import { BoardLogo } from "~/components/layout/logo/board-logo";
import { useIsMobileBoard } from "~/components/board/use-mobile-board";
import { BoardLogo, BoardLogoWithTitle } from "~/components/layout/logo/board-logo";
export const BoardSwitcherLogo = () => {
const board = useRequiredBoard();
const { data: boards = [] } = clientApi.board.getAllBoards.useQuery();
const t = useI18n();
const isMobileBoard = useIsMobileBoard();
const { data: boards = [] } = clientApi.board.getAllBoards.useQuery(undefined, { enabled: isMobileBoard });
if (!isMobileBoard) {
return (
<UnstyledButton component={Link} href="/">
<BoardLogoWithTitle size="md" hideTitleOnMobile />
</UnstyledButton>
);
}
return (
<Menu position="bottom-start" width={280}>
@@ -26,7 +36,7 @@ export const BoardSwitcherLogo = () => {
>
<Group gap="xs" wrap="nowrap">
<BoardLogo size={28} />
<Text fw={600} truncate>
<Text fw={600} truncate title={board.name}>
{board.name}
</Text>
<IconChevronDown size={16} aria-hidden />
@@ -46,7 +56,9 @@ export const BoardSwitcherLogo = () => {
leftSection={isCurrent ? <IconCheck size={20} /> : <IconLayoutBoard size={20} />}
aria-current={isCurrent ? "page" : undefined}
>
{availableBoard.name}
<Text truncate title={availableBoard.name}>
{availableBoard.name}
</Text>
</Menu.Item>
);
})}