feat: add title to dynamic section (#2614)

* feat: add title to dynamic section

* fix: formatting

* feat: use badge rather than text

* fix: use board radius

* fix: use shared.ts validation

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
This commit is contained in:
Jack Weller
2025-03-25 07:06:50 +10:00
committed by GitHub
parent b7a6d950db
commit 1dd7b1a6b9
6 changed files with 31 additions and 5 deletions

View File

@@ -10,6 +10,7 @@ export class DynamicSectionMockBuilder {
id: createId(), id: createId(),
kind: "dynamic", kind: "dynamic",
options: { options: {
title: "",
borderColor: "", borderColor: "",
}, },
layouts: [], layouts: [],

View File

@@ -1,4 +1,4 @@
import { Box, Card } from "@mantine/core"; import { Badge, Box, Card } from "@mantine/core";
import { useCurrentLayout, useRequiredBoard } from "@homarr/boards/context"; import { useCurrentLayout, useRequiredBoard } from "@homarr/boards/context";
@@ -17,7 +17,12 @@ export const BoardDynamicSection = ({ section }: Props) => {
const options = section.options; const options = section.options;
return ( return (
<Box className="grid-stack-item-content"> <Box
className="grid-stack-item-content"
style={{
overflow: "visible",
}}
>
<Card <Card
className={classes.itemCard} className={classes.itemCard}
w="100%" w="100%"
@@ -25,14 +30,28 @@ export const BoardDynamicSection = ({ section }: Props) => {
withBorder withBorder
styles={{ styles={{
root: { root: {
overflow: "visible",
"--opacity": board.opacity / 100, "--opacity": board.opacity / 100,
overflow: "hidden", "--border-color": options.borderColor || undefined,
"--border-color": options.borderColor !== "" ? options.borderColor : undefined,
}, },
}} }}
radius={board.itemRadius} radius={board.itemRadius}
p={0} p={0}
> >
{options.title && (
<Badge
pos="absolute"
top={-15}
left={10}
size="md"
radius={board.itemRadius}
color="var(--background-color)"
c="var(--mantine-color-text)"
bd="1px solid var(--border-color)"
>
{options.title}
</Badge>
)}
{/* Use unique key by layout to reinitialize gridstack */} {/* Use unique key by layout to reinitialize gridstack */}
<GridStack key={`${currentLayoutId}-${section.id}`} section={section} className="min-row" /> <GridStack key={`${currentLayoutId}-${section.id}`} section={section} className="min-row" />
</Card> </Card>

View File

@@ -17,6 +17,7 @@ export const addDynamicSectionCallback = () => (board: Board) => {
id: createId(), id: createId(),
kind: "dynamic", kind: "dynamic",
options: { options: {
title: "",
borderColor: "", borderColor: "",
}, },
layouts: createDynamicSectionLayouts(board, firstSection), layouts: createDynamicSectionLayouts(board, firstSection),

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { Button, CloseButton, ColorInput, Group, Stack, useMantineTheme } from "@mantine/core"; import { Button, CloseButton, ColorInput, Group, Stack, TextInput, useMantineTheme } from "@mantine/core";
import type { z } from "zod"; import type { z } from "zod";
import { useZodForm } from "@homarr/form"; import { useZodForm } from "@homarr/form";
@@ -30,6 +30,7 @@ export const DynamicSectionEditModal = createModal<ModalProps>(({ actions, inner
})} })}
> >
<Stack> <Stack>
<TextInput label={t("section.dynamic.option.title.label")} {...form.getInputProps("title")} />
<ColorInput <ColorInput
label={t("section.dynamic.option.borderColor.label")} label={t("section.dynamic.option.borderColor.label")}
format="hex" format="hex"

View File

@@ -980,6 +980,9 @@
"remove": "Remove dynamic section" "remove": "Remove dynamic section"
}, },
"option": { "option": {
"title": {
"label": "Title"
},
"borderColor": { "borderColor": {
"label": "Border color" "label": "Border color"
} }

View File

@@ -60,6 +60,7 @@ const emptySectionSchema = z.object({
}); });
export const dynamicSectionOptionsSchema = z.object({ export const dynamicSectionOptionsSchema = z.object({
title: z.string().max(20).default(""),
borderColor: z.string().default(""), borderColor: z.string().default(""),
}); });