import { ReactNode } from 'react';
import { IconName } from '../icon/Icon.component';
import { Props as TooltipProps } from '../tooltip/Tooltip.component';
/** A single footer action. The Modal renders the button and owns its variant. */
export type ModalAction = {
label: string;
onClick: () => void;
/** Icon name (the Modal renders the ``), shown before the label. */
icon?: IconName;
disabled?: boolean;
/** Tooltip, e.g. to explain why a disabled `confirm` can't be used yet. */
tooltip?: Omit;
};
/**
* Structured footer actions. All actions are right-aligned: `confirm` is the
* rightmost, `cancel` sits immediately to its left, and the optional neutral
* `extra` sits left of `cancel`. Two actions is the norm; three is acceptable;
* avoid four. The Modal fixes each button's variant so callers can't diverge
* from the guideline.
*/
export type ModalActions = {
/** Affirmative action, rendered rightmost. Defaults to the `primary` variant. */
confirm: ModalAction & {
variant?: 'primary' | 'danger';
};
/** Dismiss action, rendered with the `outline` variant. Label defaults to "Cancel". */
cancel?: Omit & {
label?: string;
};
/** Optional neutral tertiary action, rendered with the `secondary` variant. */
extra?: ModalAction;
};
type CommonProps = {
isOpen: boolean;
/**
* Modal title — always a short text string that mirrors the verb of the
* action that opened the modal (a "Delete node" button opens a modal
* titled "Delete node?"). The string is used as the accessible name
* (`aria-labelledby`); non-string content breaks screen-reader
* announcement.
*/
title: string
/**
* @deprecated Pass a plain string. Non-string titles violate the modal
* guideline (title is always text) and break the accessible name
* (`aria-labelledby`); support will be removed in a future major release.
*/
| Exclude;
children: ReactNode;
subTitle?: ReactNode;
/**
* When true, the modal sizes to its content (up to 90vw) instead of
* capping body content at 480px. Use for tables, complex forms, or any
* content that needs more horizontal space.
*/
wide?: boolean;
};
type WithLegacyFooter = {
/**
* Free-form footer content. Required on this branch — a modal must expose a
* footer, so callers not using `actions` have to provide one here.
*
* @deprecated Use `actions` instead. `footer` accepts arbitrary content
* and bypasses the documented stack/alignment guideline; it will be
* removed in a future major release.
*/
footer: ReactNode;
actions?: never;
};
type WithActions = {
footer?: never;
/** Structured footer actions (preferred over `footer`). */
actions: ModalActions;
};
/**
* Every modal must have a footer, so exactly one strategy is required:
* the structured `actions` prop (preferred) or the deprecated free-form
* `footer`. Passing both, or neither, fails to type-check.
*/
type FooterProps = WithLegacyFooter | WithActions;
type DialogProps = CommonProps & FooterProps & {
role?: 'dialog';
close?: () => void;
};
type AlertDialogProps = CommonProps & FooterProps & {
role: 'alertdialog';
close?: never;
};
type Props = DialogProps | AlertDialogProps;
declare const Modal: ({ isOpen, close, title, children, footer, actions, subTitle, wide, role, ...rest }: Props) => import("react").ReactPortal | null;
export { Modal };
//# sourceMappingURL=Modal.component.d.ts.map