diff --git a/apps/docs/docs/management/boards/index.mdx b/apps/docs/docs/management/boards/index.mdx index f1eb3c572..1e4e47a4f 100644 --- a/apps/docs/docs/management/boards/index.mdx +++ b/apps/docs/docs/management/boards/index.mdx @@ -12,8 +12,6 @@ tags: import iconColorImage from './img/icon-color.png' import itemRadiusImage from './img/item-radius.png' import layoutLargeImage from './img/layout-large.png' -import layoutMediumImage from './img/layout-medium.png' -import layoutSmallImage from './img/layout-small.png' Each dashboard is called a "board". You can create as many boards as you want. @@ -76,32 +74,18 @@ Homarr will fall back to the Homarr logo if nothing is set. ### Layout -In this section you can configure the different responsive layouts. Depending on your screens width the layout will change. +In this section you can configure the number of columns in the desktop layout. -![](./img/layout-settings.png) +Items and sections can be moved and resized on desktop while the board is in edit mode. +Changing the column count automatically adjusts item positions and sizes to fit the new grid. -On each element the position and size of items can be changed seperately. -When adding a new layout the position and sizes will automatically be generated depending on the column count. -When adding a new item / dynamic section that will always be 1x1 on each layout and placed on the first available position. + -#### Name +#### Mobile layout -The name of the layout can be choosen freely. It is only used for the management and will not be visible on the board. +Mobile boards use an automatic, read-only layout with two columns. Items follow the visual order of the desktop layout and are limited to two columns wide and three rows high. -#### Column count - -Amount of columns for this layout. Defines how many items can be placed in a row. When changed it will automatically adjust the position and size of the items. - -#### Breakpoint - -Minimum width of the screen where the layout will be used. -Once the minmum of the next layout is reached the layout will change. - -#### Preview - - - - +Categories and dynamic sections are not displayed as containers on mobile. Their items are included directly in the automatic grid, even when a category is collapsed on desktop. To rearrange, add, remove, or resize board items, open the board on a larger screen. ### Background #### Background image URL @@ -255,4 +239,4 @@ For the global home board you can only select boards that are public. ### Mobile home board Same as the home board, you can also set a mobile home board. -It will be used for devices that are detected as mobile devices. (Using User-Agent header) \ No newline at end of file +It will be used for devices that are detected as mobile devices. (Using User-Agent header) diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx index 0ba502a9a..eff57050a 100644 --- a/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx +++ b/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx @@ -4,30 +4,37 @@ import { Box, Stack } from "@mantine/core"; import { useCurrentLayout, useRequiredBoard } from "@homarr/boards/context"; +import { MobileBoard } from "~/components/board/mobile/mobile-board"; import { BoardCategorySection } from "~/components/board/sections/category-section"; import { BoardEmptySection } from "~/components/board/sections/empty-section"; +import { useIsMobileBoard } from "~/components/board/use-mobile-board"; import { BoardBackgroundVideo } from "~/components/layout/background"; export const ClientBoard = () => { const board = useRequiredBoard(); const currentLayoutId = useCurrentLayout(); + const isMobile = useIsMobileBoard(); const fullWidthSortedSections = board.sections .filter((section) => section.kind === "empty" || section.kind === "category") - .sort((sectionA, sectionB) => sectionA.yOffset - sectionB.yOffset); + .toSorted((sectionA, sectionB) => sectionA.yOffset - sectionB.yOffset); return ( - - {fullWidthSortedSections.map((section) => - section.kind === "empty" ? ( - - ) : ( - - ), - )} - + {isMobile ? ( + + ) : ( + + {fullWidthSortedSections.map((section) => + section.kind === "empty" ? ( + + ) : ( + + ), + )} + + )} ); }; diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_header-actions.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_header-actions.tsx index 30c91de40..822b83989 100644 --- a/apps/nextjs/src/app/[locale]/boards/(content)/_header-actions.tsx +++ b/apps/nextjs/src/app/[locale]/boards/(content)/_header-actions.tsx @@ -38,6 +38,7 @@ import { useBoardPermissions } from "~/components/board/permissions/client"; import { useCategoryActions } from "~/components/board/sections/category/category-actions"; import { CategoryEditModal } from "~/components/board/sections/category/category-edit-modal"; import { useDynamicSectionActions } from "~/components/board/sections/dynamic/dynamic-actions"; +import { useIsMobileBoard } from "~/components/board/use-mobile-board"; import { IntegrationSelectModal } from "~/components/integration/integration-select-modal"; import { HeaderButton } from "~/components/layout/header/button"; @@ -45,6 +46,7 @@ export const BoardContentHeaderActions = ({ demoReadOnly }: { demoReadOnly: bool const [isEditMode] = useEditMode(); const board = useRequiredBoard(); const { hasChangeAccess } = useBoardPermissions(board); + const isMobile = useIsMobileBoard(); if (!hasChangeAccess) { return ; @@ -52,9 +54,9 @@ export const BoardContentHeaderActions = ({ demoReadOnly }: { demoReadOnly: bool return ( <> - {isEditMode && } + {isEditMode && !isMobile && } - +