83 lines
2.5 KiB
TypeScript
83 lines
2.5 KiB
TypeScript
import { AlertTriangle, Info } from "lucide-react";
|
|
import type { ReactNode } from "react";
|
|
import AdvancedOptionsPanel from "./AdvancedOptionsPanel";
|
|
import DocumentationHelpLink from "./help/DocumentationHelpLink";
|
|
import type { DocumentationHelpReference } from "./help/documentationHelp";
|
|
|
|
export type ActionBlockerReason = {
|
|
summary: ReactNode;
|
|
details?: ReactNode;
|
|
requiredAction?: ReactNode;
|
|
actor?: ReactNode;
|
|
target?: ReactNode;
|
|
technicalDetails?: ReactNode;
|
|
};
|
|
|
|
export type ActionBlockerLabels = {
|
|
requiredAction?: ReactNode;
|
|
actor?: ReactNode;
|
|
target?: ReactNode;
|
|
technicalDetails?: ReactNode;
|
|
};
|
|
|
|
type ActionBlockerHintProps = {
|
|
reason: ActionBlockerReason;
|
|
tone?: "info" | "warning" | "danger";
|
|
className?: string;
|
|
labels?: ActionBlockerLabels;
|
|
documentation?: DocumentationHelpReference;
|
|
};
|
|
|
|
function joinClasses(...classes: Array<string | undefined | false>) {
|
|
return classes.filter(Boolean).join(" ");
|
|
}
|
|
|
|
export default function ActionBlockerHint({
|
|
reason,
|
|
tone = "warning",
|
|
className = "",
|
|
labels = {},
|
|
documentation
|
|
}: ActionBlockerHintProps) {
|
|
const Icon = tone === "info" ? Info : AlertTriangle;
|
|
const hasActionRows = Boolean(reason.requiredAction || reason.actor || reason.target);
|
|
|
|
return (
|
|
<section className={joinClasses("action-blocker-hint", `tone-${tone}`, className)}>
|
|
<Icon className="action-blocker-icon" size={18} aria-hidden="true" />
|
|
<div className="action-blocker-copy">
|
|
<strong>{reason.summary}</strong>
|
|
{reason.details && <p>{reason.details}</p>}
|
|
{hasActionRows && (
|
|
<dl>
|
|
{reason.requiredAction && (
|
|
<>
|
|
<dt>{labels.requiredAction ?? "Required action"}</dt>
|
|
<dd>{reason.requiredAction}</dd>
|
|
</>
|
|
)}
|
|
{reason.actor && (
|
|
<>
|
|
<dt>{labels.actor ?? "Who can fix it"}</dt>
|
|
<dd>{reason.actor}</dd>
|
|
</>
|
|
)}
|
|
{reason.target && (
|
|
<>
|
|
<dt>{labels.target ?? "Where to go"}</dt>
|
|
<dd>{reason.target}</dd>
|
|
</>
|
|
)}
|
|
</dl>
|
|
)}
|
|
{reason.technicalDetails && (
|
|
<AdvancedOptionsPanel title={labels.technicalDetails ?? "Technical details"} className="action-blocker-technical">
|
|
<div>{reason.technicalDetails}</div>
|
|
</AdvancedOptionsPanel>
|
|
)}
|
|
{documentation && <DocumentationHelpLink reference={documentation} />}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|