Centralize metric and description layouts

This commit is contained in:
2026-08-18 11:30:39 +02:00
parent 6814a41ae4
commit ee5c881df9
12 changed files with 241 additions and 45 deletions
+1
View File
@@ -38,6 +38,7 @@ export default function ConfirmDialog({
open={open}
title={title}
role="alertdialog"
size="small"
className="confirm-dialog"
footerClassName="button-row compact-actions"
closeOnBackdrop={!busy}
@@ -512,7 +512,6 @@ export default function CredentialEnvelopeManager({
helpModuleId="access"
onClose={closeEditor}
closeDisabled={saving}
className="adaptive-config-dialog"
footerClassName="button-row compact-actions"
footer={
<>
+59
View File
@@ -0,0 +1,59 @@
import type { HTMLAttributes, ReactNode } from "react";
export type DescriptionListColumns = 1 | 2 | 3 | 4 | 5;
export type DescriptionListDensity = "compact" | "default";
export type DescriptionListCollapseAt = "narrow" | "workspace" | "standard" | "wide" | "never";
export type DescriptionListVariant = "stacked" | "inline";
export type DescriptionListTermWidth = "compact" | "default" | "wide";
export type DescriptionListProps = HTMLAttributes<HTMLDListElement> & {
children: ReactNode;
columns?: DescriptionListColumns;
density?: DescriptionListDensity;
collapseAt?: DescriptionListCollapseAt;
variant?: DescriptionListVariant;
termWidth?: DescriptionListTermWidth;
};
export default function DescriptionList({
children,
columns,
density = "default",
collapseAt = "workspace",
variant = "stacked",
termWidth = "default",
className = "",
...props
}: DescriptionListProps) {
const resolvedColumns = columns ?? (variant === "inline" ? 1 : 2);
return (
<dl
{...props}
className={[
"description-list-layout",
`description-list-columns-${resolvedColumns}`,
`description-list-density-${density}`,
`description-list-collapse-${collapseAt}`,
`description-list-${variant}`,
`description-list-term-${termWidth}`,
className
].filter(Boolean).join(" ")}
>
{children}
</dl>
);
}
export type DescriptionItemProps = HTMLAttributes<HTMLDivElement> & {
term: ReactNode;
children: ReactNode;
};
export function DescriptionItem({ term, children, className = "", ...props }: DescriptionItemProps) {
return (
<div {...props} className={["description-list-item", className].filter(Boolean).join(" ")}>
<dt>{term}</dt>
<dd>{children}</dd>
</div>
);
}
+44
View File
@@ -0,0 +1,44 @@
import type { HTMLAttributes, ReactNode } from "react";
export type MetricGridColumns = 1 | 2 | 3 | 4 | 5 | "auto";
export type MetricGridDensity = "compact" | "default" | "loose";
export type MetricGridSpacing = "block" | "inset" | "none";
export type MetricGridMinimum = "fluid" | "compact" | "default" | "wide";
export type MetricGridCollapseAt = "narrow" | "workspace" | "standard" | "wide" | "never";
export type MetricGridProps = HTMLAttributes<HTMLDivElement> & {
children: ReactNode;
columns?: MetricGridColumns;
density?: MetricGridDensity;
spacing?: MetricGridSpacing;
minimum?: MetricGridMinimum;
collapseAt?: MetricGridCollapseAt;
};
export default function MetricGrid({
children,
columns = 4,
density = "default",
spacing = "block",
minimum = "default",
collapseAt = "workspace",
className = "",
...props
}: MetricGridProps) {
return (
<div
{...props}
className={[
"metric-group-layout",
`metric-group-columns-${columns}`,
`metric-group-density-${density}`,
`metric-group-spacing-${spacing}`,
`metric-group-minimum-${minimum}`,
`metric-group-collapse-${collapseAt}`,
className
].filter(Boolean).join(" ")}
>
{children}
</div>
);
}