Merge branch 'dev' into feat/impeccable-uiux-fixes

This commit is contained in:
Thomas authored and GitHub committed 2026-05-28 10:58:29 +02:00
commit d5fd6905ea
176 files changed
+3068 -6219

No files matched your search

@@ -3,6 +3,7 @@ import { useDisclosure } from "@mantine/hooks";
import { IconChevronDown, IconChevronUp } from "@tabler/icons-react";
import { clientApi } from "@homarr/api/client";
import { useSession } from "@homarr/auth/client";
import { useRequiredBoard } from "@homarr/boards/context";
import type { CategorySection } from "~/app/[locale]/boards/_types";
@@ -10,19 +11,36 @@ import { CategoryMenu } from "./category/category-menu";
import { GridStack } from "./gridstack/gridstack";
import classes from "./item.module.css";
const localStorageKey = (sectionId: string) => `homarr-section-collapsed-${sectionId}`;
interface Props {
section: CategorySection;
}
export const BoardCategorySection = ({ section }: Props) => {
const { status } = useSession();
const { mutate } = clientApi.section.changeCollapsed.useMutation();
const board = useRequiredBoard();
const [opened, { toggle }] = useDisclosure(section.collapsed, {
const initialCollapsed =
typeof window !== "undefined"
? (localStorage.getItem(localStorageKey(section.id)) ?? String(section.collapsed)) === "true"
: section.collapsed;
const [opened, { toggle }] = useDisclosure(initialCollapsed, {
onOpen() {
mutate({ sectionId: section.id, collapsed: true });
if (status === "authenticated") {
mutate({ sectionId: section.id, collapsed: true });
} else if (status === "unauthenticated") {
localStorage.setItem(localStorageKey(section.id), "true");
}
},
onClose() {
mutate({ sectionId: section.id, collapsed: false });
if (status === "authenticated") {
mutate({ sectionId: section.id, collapsed: false });
} else if (status === "unauthenticated") {
localStorage.setItem(localStorageKey(section.id), "false");
}
},
});
@@ -38,7 +56,7 @@ export const BoardCategorySection = ({ section }: Props) => {
</UnstyledButton>
<CategoryMenu category={section} />
</Group>
<Collapse in={opened} p="sm" pt={0}>
<Collapse expanded={opened} p="sm" pt={0}>
<GridStack section={section} />
</Collapse>
</Stack>
@@ -1,6 +1,6 @@
import type { RefObject } from "react";
import type { Ref, RefObject } from "react";
import { createRef, useCallback, useEffect, useRef } from "react";
import { useElementSize } from "@mantine/hooks";
import { useElementSize, useMergedRef } from "@mantine/hooks";
import { useCurrentLayout, useRequiredBoard } from "@homarr/boards/context";
import { useEditMode } from "@homarr/boards/edit-mode";
@@ -13,7 +13,7 @@ import { useSectionActions } from "../section-actions";
import { initializeGridstack } from "./init-gridstack";
export interface UseGridstackRefs {
wrapper: RefObject<HTMLDivElement | null>;
wrapper: Ref<HTMLDivElement | null>;
items: RefObject<Record<string, RefObject<GridItemHTMLElement | null>>>;
gridstack: RefObject<GridStack | null>;
}
@@ -59,8 +59,9 @@ export const useGridstack = (section: Omit<Section, "items">, itemIds: string[])
const { moveAndResizeItem, moveItemToSection } = useItemActions();
const { moveAndResizeInnerSection, moveInnerSectionToSection } = useSectionActions();
// define reference for wrapper - is used to calculate the width of the wrapper
const { ref: wrapperRef, width, height } = useElementSize<HTMLDivElement>();
const wrapperElementRef = useRef<HTMLDivElement | null>(null);
const { ref: measureWrapperRef, width, height } = useElementSize<HTMLDivElement>();
const wrapperRef = useMergedRef(measureWrapperRef, wrapperElementRef);
// references to the diffrent items contained in the gridstack
const itemRefs = useRef<Record<string, RefObject<GridItemHTMLElement | null>>>({});
// reference of the gridstack object for modifications after initialization
@@ -193,7 +194,7 @@ export const useGridstack = (section: Omit<Section, "items">, itemIds: string[])
itemIds,
refs: {
items: itemRefs,
wrapper: wrapperRef,
wrapper: wrapperElementRef,
gridstack: gridRef,
},
sectionColumnCount: columnCount,
@@ -276,7 +277,7 @@ export const useGridstack = (section: Omit<Section, "items">, itemIds: string[])
useCssVariableConfiguration({
columnCount,
gridRef,
wrapperRef,
wrapperRef: wrapperElementRef,
width,
height,
isDynamic: section.kind === "dynamic",
@@ -293,7 +294,7 @@ export const useGridstack = (section: Omit<Section, "items">, itemIds: string[])
interface UseCssVariableConfiguration {
gridRef: UseGridstackRefs["gridstack"];
wrapperRef: UseGridstackRefs["wrapper"];
wrapperRef: RefObject<HTMLDivElement | null>;
width: number;
height: number;
columnCount: number;