NODEDC_DESIGN_GUIDELINE/packages/ui-react/src/ApplicationShell.tsx

97 lines
3.0 KiB
TypeScript

import type { HTMLAttributes, ReactNode } from "react";
import { cn } from "./cn";
import { Icon } from "./Icon";
export interface ApplicationShellProps extends Omit<HTMLAttributes<HTMLDivElement>, "content"> {
header: ReactNode;
stage: ReactNode;
navigation?: ReactNode;
content?: ReactNode;
navigationOpen?: boolean;
contentOpen?: boolean;
contentExpanded?: boolean;
}
export function ApplicationShell({
header,
stage,
navigation,
content,
navigationOpen = false,
contentOpen = false,
contentExpanded = false,
className,
...props
}: ApplicationShellProps) {
return (
<div
className={cn("nodedc-app-shell", className)}
data-navigation-open={navigationOpen ? "true" : undefined}
data-content-open={contentOpen ? "true" : undefined}
data-content-expanded={contentOpen && contentExpanded ? "true" : undefined}
{...props}
>
{header}
<main className="nodedc-app-shell__main">
<div className="nodedc-app-shell__stage">{stage}</div>
{navigationOpen && navigation ? <div className="nodedc-app-shell__navigation">{navigation}</div> : null}
{contentOpen && content ? <div className="nodedc-app-shell__content">{content}</div> : null}
</main>
</div>
);
}
export interface ApplicationPanelProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
eyebrow?: ReactNode;
title: ReactNode;
description?: ReactNode;
expanded?: boolean;
expandLabel?: string;
closeLabel?: string;
onExpandedChange?: (expanded: boolean) => void;
onClose: () => void;
children: ReactNode;
}
export function ApplicationPanel({
eyebrow,
title,
description,
expanded = false,
expandLabel = "Развернуть окно",
closeLabel = "Закрыть окно",
onExpandedChange,
onClose,
children,
className,
...props
}: ApplicationPanelProps) {
return (
<section className={cn("nodedc-application-panel", className)} data-expanded={expanded ? "true" : undefined} {...props}>
<header className="nodedc-application-panel__head">
<div className="nodedc-application-panel__titles">
{eyebrow ? <span>{eyebrow}</span> : null}
<h1>{title}</h1>
{description ? <p>{description}</p> : null}
</div>
<div className="nodedc-application-panel__actions">
{onExpandedChange ? (
<button
type="button"
className="nodedc-application-panel__action"
aria-label={expanded ? "Свернуть окно" : expandLabel}
onClick={() => onExpandedChange(!expanded)}
>
<Icon name={expanded ? "minimize" : "expand"} />
</button>
) : null}
<button type="button" className="nodedc-application-panel__action" aria-label={closeLabel} onClick={onClose}>
<Icon name="close" />
</button>
</div>
</header>
<div className="nodedc-application-panel__body">{children}</div>
</section>
);
}