* refactor(shared-components): move core primitives under core * refactor(shared-components): restore i18n strings path * fix(shared-components): repair typedoc story imports * fix(shared-components): align newer imports with core paths * test(shared-components): add core visual baselines * refactor(shared-components): move virtualized list to core root
93 lines
2.6 KiB
TypeScript
93 lines
2.6 KiB
TypeScript
/*
|
|
* Copyright (c) 2025 Element Creations Ltd.
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
* Please see LICENSE files in the repository root for full details.
|
|
*/
|
|
|
|
import classNames from "classnames";
|
|
import React, {
|
|
type MouseEventHandler,
|
|
type ReactElement,
|
|
type ReactNode,
|
|
type PropsWithChildren,
|
|
useMemo,
|
|
type HTMLAttributes,
|
|
} from "react";
|
|
import { Button } from "@vector-im/compound-web";
|
|
import CheckCircleIcon from "@vector-im/compound-design-tokens/assets/web/icons/check-circle";
|
|
import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error";
|
|
import InfoIcon from "@vector-im/compound-design-tokens/assets/web/icons/info";
|
|
|
|
import styles from "./Banner.module.css";
|
|
import { _t } from "../../core/i18n/i18n";
|
|
|
|
interface BannerProps {
|
|
/**
|
|
* The type of the status banner.
|
|
*/
|
|
type?: "success" | "info" | "critical";
|
|
|
|
/**
|
|
* The banner avatar.
|
|
*/
|
|
avatar?: React.ReactNode;
|
|
|
|
/**
|
|
* Actions presented to the user in the right-hand side of the banner alongside the dismiss button.
|
|
*/
|
|
actions?: ReactNode;
|
|
/**
|
|
* Called when the user presses the "dismiss" button.
|
|
*/
|
|
onClose?: MouseEventHandler<HTMLButtonElement>;
|
|
}
|
|
|
|
/**
|
|
* A banner component used for displaying user-facing information above the message composer.
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* <Banner onClose={onCloseHandler} />
|
|
* ```
|
|
*/
|
|
export function Banner({
|
|
type,
|
|
children,
|
|
avatar,
|
|
className,
|
|
actions,
|
|
onClose,
|
|
...props
|
|
}: PropsWithChildren<BannerProps & HTMLAttributes<HTMLDivElement>>): ReactElement {
|
|
const classes = classNames(styles.banner, className);
|
|
|
|
const icon = useMemo((): ReactElement => {
|
|
switch (type) {
|
|
case "critical":
|
|
return <ErrorIcon fontSize={24} />;
|
|
case "info":
|
|
return <InfoIcon fontSize={24} />;
|
|
case "success":
|
|
return <CheckCircleIcon fontSize={24} />;
|
|
default:
|
|
return <InfoIcon fontSize={24} />;
|
|
}
|
|
}, [type]);
|
|
|
|
return (
|
|
<div {...props} className={classes} data-type={type}>
|
|
<div className={styles.icon}>{avatar ?? icon}</div>
|
|
<div className={styles.content}>{children}</div>
|
|
<div className={styles.actions}>
|
|
{actions}
|
|
{onClose && (
|
|
<Button kind="secondary" size="sm" onClick={onClose}>
|
|
{_t("action|dismiss")}
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|