Add shared WebUI layout primitives

This commit is contained in:
2026-08-18 10:42:55 +02:00
parent dd7ad4d9c7
commit 6814a41ae4
22 changed files with 574 additions and 111 deletions
+88
View File
@@ -0,0 +1,88 @@
import type { HTMLAttributes, ReactNode } from "react";
import { usePlatformLanguage } from "../i18n/LanguageContext";
import type { PlatformInterfaceIdentityProps } from "../types";
export type ActionToolbarDensity = "compact" | "default";
export type ActionToolbarSurface = "plain" | "subtle";
export type ActionToolbarWrap = "responsive" | "always" | "never";
export type ActionToolbarProps = PlatformInterfaceIdentityProps & Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
children: ReactNode;
label?: string;
density?: ActionToolbarDensity;
surface?: ActionToolbarSurface;
wrap?: ActionToolbarWrap;
};
export default function ActionToolbar({
children,
label,
density = "default",
surface = "plain",
wrap = "responsive",
className = "",
role,
"aria-label": ariaLabel,
interfaceId,
helpContextId,
helpModuleId,
helpTopicId,
...props
}: ActionToolbarProps) {
const { translateText } = usePlatformLanguage();
const translatedLabel = label || ariaLabel ? translateText(label ?? ariaLabel ?? "") : undefined;
return (
<div
{...props}
className={[
"action-toolbar",
`action-toolbar-density-${density}`,
`action-toolbar-surface-${surface}`,
`action-toolbar-wrap-${wrap}`,
className
].filter(Boolean).join(" ")}
role={role ?? (translatedLabel ? "toolbar" : undefined)}
aria-label={translatedLabel}
data-help-scope="toolbar"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
>
{children}
</div>
);
}
export type ToolbarGroupProps = HTMLAttributes<HTMLDivElement> & {
children: ReactNode;
align?: "start" | "center" | "end";
grow?: boolean;
};
export function ToolbarGroup({
children,
align = "start",
grow = false,
className = "",
...props
}: ToolbarGroupProps) {
return (
<div
{...props}
className={[
"action-toolbar-group",
`action-toolbar-group-${align}`,
grow ? "action-toolbar-group-grow" : "",
className
].filter(Boolean).join(" ")}
>
{children}
</div>
);
}
export function ToolbarSpacer({ className = "", ...props }: HTMLAttributes<HTMLSpanElement>) {
return <span {...props} className={["action-toolbar-spacer", className].filter(Boolean).join(" ")} aria-hidden="true" />;
}