diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/mui/Alert.tsx')
-rw-r--r-- | packages/taler-wallet-webextension/src/mui/Alert.tsx | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/packages/taler-wallet-webextension/src/mui/Alert.tsx b/packages/taler-wallet-webextension/src/mui/Alert.tsx new file mode 100644 index 000000000..22ea0b8ab --- /dev/null +++ b/packages/taler-wallet-webextension/src/mui/Alert.tsx @@ -0,0 +1,175 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +import { TranslatedString } from "@gnu-taler/taler-util"; +import { css } from "@linaria/core"; +import { ComponentChildren, h, VNode } from "preact"; +// eslint-disable-next-line import/extensions +import CloseIcon from "../svg/close_24px.inline.svg"; +import ErrorOutlineIcon from "../svg/error_outline_outlined_24px.inline.svg"; +import InfoOutlinedIcon from "../svg/info_outlined_24px.inline.svg"; +import ReportProblemOutlinedIcon from "../svg/report_problem_outlined_24px.inline.svg"; +import SuccessOutlinedIcon from "../svg/success_outlined_24px.inline.svg"; +import { IconButton } from "./Button.js"; +import { darken, lighten } from "./colors/manipulation.js"; +import { Paper } from "./Paper.js"; +import { theme } from "./style.jsx"; +import { Typography } from "./Typography.js"; + +const defaultIconMapping = { + success: SuccessOutlinedIcon, + warning: ReportProblemOutlinedIcon, + error: ErrorOutlineIcon, + info: InfoOutlinedIcon, +}; + +const baseStyle = css` + background-color: transparent; + display: flex; + padding: 6px 16px; +`; + +const colorVariant = { + standard: css` + color: var(--color-light-06); + background-color: var(--color-background-light-09); + `, + outlined: css` + color: var(--color-light-06); + border-width: 1px; + border-style: solid; + border-color: var(--color-light); + `, + filled: css` + color: "#fff"; + font-weight: ${theme.typography.fontWeightMedium}; + background-color: var(--color-main); + `, +}; + +interface Props { + title?: TranslatedString; + variant?: "filled" | "outlined" | "standard"; + role?: string; + onClose?: () => Promise<void>; + // icon: VNode; + severity?: "info" | "warning" | "success" | "error"; + children: ComponentChildren; + icon?: boolean; +} + +const getColor = theme.palette.mode === "light" ? darken : lighten; +const getBackgroundColor = theme.palette.mode === "light" ? lighten : darken; + +function Icon({ svg }: { svg: VNode }): VNode { + return ( + <div + class={css` + margin-right: 12px; + padding: 7px 0px; + display: flex; + font-size: 22px; + opacity: 0.9; + fill: currentColor; + `} + dangerouslySetInnerHTML={{ __html: svg as any }} + ></div> + ); +} + +function Action({ children }: { children: ComponentChildren }): VNode { + return ( + <div + class={css` + display: flex; + align-items: flex-start; + padding: 4px 0px 0px 16px; + margin-left: auto; + margin-right: -8px; + `} + > + {children} + </div> + ); +} + +function Message({ + title, + children, +}: { + title?: TranslatedString; + children: ComponentChildren; +}): VNode { + return ( + <div + class={css` + padding: 8px 0px; + width: calc(100% - 48px - 36px); + `} + > + {title && ( + <Typography + class={css` + font-weight: ${theme.typography.fontWeightBold}; + `} + gutterBottom + > + {title} + </Typography> + )} + {children} + </div> + ); +} + +export function Alert({ + variant = "standard", + severity = "success", + title, + children, + icon, + onClose, + ...rest +}: Props): VNode { + return ( + <Paper + class={[ + theme.typography.body2, + baseStyle, + severity && colorVariant[variant], + ].join(" ")} + style={{ + "--color-light-06": getColor(theme.palette[severity].light, 0.6), + "--color-background-light-09": getBackgroundColor( + theme.palette[severity].light, + 0.9, + ), + "--color-main": theme.palette[severity].main, + "--color-light": theme.palette[severity].light, + // ...(style as any), + textAlign: "left", + }} + elevation={1} + > + {icon != false ? <Icon svg={defaultIconMapping[severity]} /> : null} + <Message title={title}>{children}</Message> + {onClose && ( + <Action> + <IconButton svg={CloseIcon} onClick={onClose} /> + </Action> + )} + </Paper> + ); +} |