Files
homarr/packages/widgets/src/widget-card-shell.tsx
T

95 lines
2.5 KiB
TypeScript

"use client";
import type { AriaRole, CSSProperties, PropsWithChildren, Ref } from "react";
import type { CardProps } from "@mantine/core";
import { Badge, Card } from "@mantine/core";
import combineClasses from "clsx";
import type { WidgetKind } from "@homarr/definitions";
import type { BoardItemAdvancedOptions } from "@homarr/validation/shared";
import classes from "./widget-card-shell.module.css";
const getOverflow = (kind: WidgetKind, hasCustomCssClasses: boolean): CSSProperties => {
if (kind === "systemResources") return { overflowX: "visible", overflowY: "visible" };
if (kind === "iframe" || kind === "assistant") return { overflowX: "hidden", overflowY: "hidden" };
if (hasCustomCssClasses) return {};
return { overflowX: "hidden", overflowY: "auto" };
};
interface WidgetCardShellProps extends PropsWithChildren<Omit<CardProps, "className" | "styles">> {
kind: WidgetKind;
advancedOptions: BoardItemAdvancedOptions;
opacity: number;
className?: string;
innerRef?: Ref<HTMLDivElement>;
id?: string;
role?: AriaRole;
"aria-label"?: string;
"data-advanced-focus-surface"?: boolean;
"data-grid-item-content"?: boolean;
}
export const WidgetCardShell = ({
kind,
advancedOptions,
opacity,
className,
innerRef,
children,
...cardProps
}: WidgetCardShellProps) => (
<Card
{...cardProps}
ref={innerRef}
className={combineClasses(
classes.card,
`${kind}-wrapper`,
"board-grid-item-content",
advancedOptions.customCssClasses.join(" "),
className,
)}
styles={{
root: {
"--opacity": opacity,
"--border-color": advancedOptions.borderColor || undefined,
containerType: "size",
...getOverflow(kind, advancedOptions.customCssClasses.length > 0),
} as CSSProperties,
}}
>
{children}
</Card>
);
interface WidgetTitleBadgeProps {
advancedOptions: BoardItemAdvancedOptions;
opacity: number;
radius: CardProps["radius"];
}
export const WidgetTitleBadge = ({ advancedOptions, opacity, radius }: WidgetTitleBadgeProps) => {
if (!advancedOptions.title?.trim()) return null;
return (
<Badge
pos="absolute"
style={{ zIndex: "var(--mantine-z-index-app)" }}
top={2}
left={16}
size="xs"
radius={radius}
styles={{
root: {
"--border-color": advancedOptions.borderColor || undefined,
"--opacity": opacity,
} as CSSProperties,
}}
className={classes.title}
c="var(--mantine-color-text)"
>
{advancedOptions.title}
</Badge>
);
};