fix(widgets): restore compact v1 surfaces (#6710)

This commit is contained in:
Thomas authored and GitHub committed 2026-08-27 11:08:17 +02:00
1 parent 1b2f1bd720
commit 643ecf3df7
105 files changed
+1603 -1285

No files matched your search

+3 -29
View File
@@ -16,7 +16,6 @@ import {
Stack,
Text,
Tooltip,
VisuallyHidden,
} from "@mantine/core";
import {
IconBrandDocker,
@@ -111,33 +110,11 @@ const ContainerStateBadge = ({ state }: { state: ContainerState }) => {
);
};
const ContainerStateDot = ({ state }: { state: ContainerState }) => {
const t = useI18n("docker.field.state.option");
const label = t(state);
return (
<Tooltip label={label} withArrow>
<Box component="span" style={{ display: "inline-flex", flexShrink: 0 }}>
<Box
component="span"
aria-hidden="true"
w={8}
h={8}
bg={`${containerStateColorMap[state]}.6`}
style={{ borderRadius: "50%" }}
/>
<VisuallyHidden>{label}</VisuallyHidden>
</Box>
</Tooltip>
);
};
const createColumns = (
t: ReturnType<typeof useI18n<"docker">>,
tCommon: ReturnType<typeof useI18n<"common">>,
handlers: ContainerActionHandlers,
sortingEnabled: boolean,
inlineState: boolean,
): DataTableColumn<DockerContainer>[] => [
{
accessor: "name",
@@ -147,7 +124,6 @@ const createColumns = (
sortable: sortingEnabled,
render: (container) => (
<Group gap="xs" wrap="nowrap" style={{ overflow: "hidden" }}>
{inlineState && <ContainerStateDot state={container.state} />}
<Avatar
variant="outline"
radius="sm"
@@ -387,14 +363,12 @@ export default function DockerWidget({
() => getDockerColumnVisibility(options.columns, width, isAdvanced),
[isAdvanced, options.columns, width],
);
const inlineState =
!isAdvanced && width < 340 && options.columns.includes("name") && options.columns.includes("state");
const columns = useMemo(() => {
const sortingEnabled = (isAdvanced || options.enableRowSorting) && !isEditMode;
return createColumns(t, tCommon, actionHandlers, sortingEnabled, inlineState).filter(
return createColumns(t, tCommon, actionHandlers, sortingEnabled).filter(
({ accessor }) => columnVisibility[String(accessor) as keyof typeof columnVisibility],
);
}, [actionHandlers, columnVisibility, inlineState, isAdvanced, isEditMode, options.enableRowSorting, t, tCommon]);
}, [actionHandlers, columnVisibility, isAdvanced, isEditMode, options.enableRowSorting, t, tCommon]);
const { effectiveColumns, storeKey } = usePersistedTableLayout({
columns,
columnAccessors,
@@ -435,7 +409,7 @@ export default function DockerWidget({
<Box style={{ flex: 1, minHeight: 0 }}>
<HomarrDataTable
isEditMode={isEditMode}
cellPadding="2px 8px"
cellPadding={isAdvanced || width < 400 ? "2px 8px" : "4px 8px"}
className="docker-table"
rowCursor="default"
fetching={isFetching && containers.length === 0}
+23 -16
View File
@@ -5,27 +5,34 @@ import { getDockerColumnVisibility, getDockerFooterVisibility } from "./layout";
const columns = ["name", "state", "host", "cpuUsage", "memoryUsage", "actions"] as const;
describe("getDockerColumnVisibility", () => {
test("keeps only essential columns in a narrow compact widget", () => {
test("keeps every configured column in a narrow compact widget", () => {
expect(getDockerColumnVisibility(columns, 240, false)).toEqual({
name: true,
state: false,
host: false,
cpuUsage: false,
memoryUsage: false,
state: true,
host: true,
cpuUsage: true,
memoryUsage: true,
actions: true,
});
});
test("reveals compact metrics as width becomes available", () => {
expect(getDockerColumnVisibility(columns, 440, false)).toMatchObject({
test("honors the configured compact column set at every width", () => {
expect(getDockerColumnVisibility(["name", "memoryUsage"], 200, false)).toEqual({
name: true,
state: false,
host: false,
cpuUsage: true,
memoryUsage: false,
cpuUsage: false,
memoryUsage: true,
actions: false,
});
expect(getDockerColumnVisibility(["name", "memoryUsage"], 800, false)).toEqual({
name: true,
state: false,
host: false,
cpuUsage: false,
memoryUsage: true,
actions: false,
});
});
test("keeps a configured state column when there is no name column for the inline dot", () => {
expect(getDockerColumnVisibility(["state"], 240, false).state).toBe(true);
});
test("uses every expert column in advanced mode", () => {
@@ -41,9 +48,9 @@ describe("getDockerColumnVisibility", () => {
});
describe("getDockerFooterVisibility", () => {
test("reveals totals only when they fit", () => {
expect(getDockerFooterVisibility(300, false)).toEqual({ footer: true, cpu: false, memory: false });
expect(getDockerFooterVisibility(400, false)).toEqual({ footer: true, cpu: true, memory: false });
test("shows the full compact footer above its threshold", () => {
expect(getDockerFooterVisibility(256, false)).toEqual({ footer: false, cpu: false, memory: false });
expect(getDockerFooterVisibility(257, false)).toEqual({ footer: true, cpu: true, memory: true });
});
test("keeps every total in advanced mode", () => {
+7 -7
View File
@@ -2,7 +2,7 @@ export type DockerColumn = "name" | "state" | "host" | "cpuUsage" | "memoryUsage
export const getDockerColumnVisibility = (
configuredColumns: readonly DockerColumn[],
width: number,
_width: number,
isAdvanced: boolean,
): Record<DockerColumn, boolean> => {
const configured = new Set(configuredColumns);
@@ -10,16 +10,16 @@ export const getDockerColumnVisibility = (
return {
name: isVisible("name"),
state: isVisible("state") && (isAdvanced || width >= 340 || !configured.has("name")),
host: isVisible("host") && (isAdvanced || width >= 640),
cpuUsage: isVisible("cpuUsage") && (isAdvanced || width >= 420),
memoryUsage: isVisible("memoryUsage") && (isAdvanced || width >= 520),
state: isVisible("state"),
host: isVisible("host"),
cpuUsage: isVisible("cpuUsage"),
memoryUsage: isVisible("memoryUsage"),
actions: isVisible("actions"),
};
};
export const getDockerFooterVisibility = (width: number, isAdvanced: boolean) => ({
footer: isAdvanced || width > 256,
cpu: isAdvanced || width >= 360,
memory: isAdvanced || width >= 480,
cpu: isAdvanced || width > 256,
memory: isAdvanced || width > 256,
});