diff --git a/docs/management/boards/img/create-board-modal.png b/docs/management/boards/img/create-board-modal.png index a3f9322f..9415434c 100644 Binary files a/docs/management/boards/img/create-board-modal.png and b/docs/management/boards/img/create-board-modal.png differ diff --git a/docs/management/boards/img/layout-settings.png b/docs/management/boards/img/layout-settings.png index 7266015c..bbc57d5d 100644 Binary files a/docs/management/boards/img/layout-settings.png and b/docs/management/boards/img/layout-settings.png differ diff --git a/docs/management/boards/index.mdx b/docs/management/boards/index.mdx index 448be873..19b1bb77 100644 --- a/docs/management/boards/index.mdx +++ b/docs/management/boards/index.mdx @@ -14,6 +14,7 @@ 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' +import {GridLayout} from '@site/src/components/grid-layout'; Each dashboard is called a "board". You can create as many boards as you want. @@ -32,6 +33,14 @@ When creating a board, the availability of the board name will be checked for yo The name must not include any special characters and must be at least one character long. Underscores and hyphen-minus are allowed. +### Layout mode + +There are two layout modes available. They define how the board will behave on different screen sizes. +- **Auto:** The board items will adjust for different screen sizes automatically based on the base layout. +- **Custom:** The board items have to be adjusted manually for different screen sizes. + +For visualization of the two modes, see [here](#visualizations). + ### Column count Homarr has a complex drag and drop system that can be used from the browser. The column count defines how many horizontal columns are available to drag and drop elements to. @@ -84,6 +93,59 @@ 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. +#### Layout mode + +There are two layout modes available. They define how the board will behave on different screen sizes. +- **Auto:** The board items will adjust for different screen sizes automatically based on the base layout +- **Custom:** The board items have to be adjusted manually for different screen sizes. + +##### Visualizations + +This is how the different layout modes behave on different screen sizes with the 8 column layout as base: + +
+ + + + + +
+ +Order of items is defined by their position (top left to bottom right, row for row). +If the next item does not fit in the current row, it will be placed in the next row (see 4 in medium layout). +If an item is small enough to fit into one of the gaps, it will be placed there (see 6 in medium layout). +If the size of an item is to large to fix into the amount of columns available, it will automatically be resized to fit the entire width (see 3 in last layout). + +#### Base layout + +When using the layout mode **Auto** one of the layouts has to be defined as the base layout. +It will be used to calculate position and size of items for other responsive layouts automatically. + + #### Name The name of the layout can be choosen freely. It is only used for the management and will not be visible on the board. diff --git a/src/components/grid-layout.tsx b/src/components/grid-layout.tsx new file mode 100644 index 00000000..7336af89 --- /dev/null +++ b/src/components/grid-layout.tsx @@ -0,0 +1,59 @@ +interface GridItem { + xOffset: number; + yOffset: number; + width?: number; + height?: number; + content: string; +} + +interface GridLayoutProps { + gap: number; + width: number; + columns: number; + items: GridItem[]; +} + +export const GridLayout = (props: GridLayoutProps) => { + const size = (props.width - props.gap * (props.columns - 1)) / props.columns; + const rows = Math.max(...props.items.map((item) => item.yOffset + (item.height ?? 1))); + + return ( +
+ {props.items.map((item) => ( + + ))} +
+ ); +}; + +interface GridItemProps { + item: GridItem; + size: number; + gap: number; +} + +const GridItem = (props: GridItemProps) => { + return ( +
+ {props.item.content} +
+ ); +};