mirror of
https://github.com/tutao/tutanota.git
synced 2025-10-19 07:53:47 +00:00
110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
import { AllIcons, Icon } from "./Icon.js"
|
|
import m, { Children, Component, Vnode } from "mithril"
|
|
import { theme } from "../theme.js"
|
|
import type { InfoLink, TranslationKey } from "../../misc/LanguageViewModel.js"
|
|
import { lang } from "../../misc/LanguageViewModel.js"
|
|
import type { ButtonAttrs } from "./Button.js"
|
|
import { Button, ButtonType } from "./Button.js"
|
|
import { NavButton } from "./NavButton.js"
|
|
import type { lazy } from "@tutao/tutanota-utils"
|
|
import { isNotNull } from "@tutao/tutanota-utils"
|
|
import { Icons } from "./icons/Icons.js"
|
|
import { px, size } from "../size.js"
|
|
|
|
export const enum BannerType {
|
|
Info = "info",
|
|
Warning = "warning",
|
|
}
|
|
|
|
export type BannerButtonAttrs = Omit<ButtonAttrs, "type">
|
|
|
|
export interface InfoBannerAttrs {
|
|
message: TranslationKey | lazy<Children>
|
|
icon: AllIcons
|
|
helpLink?: InfoLink | null
|
|
buttons: ReadonlyArray<BannerButtonAttrs | null>
|
|
type?: BannerType
|
|
}
|
|
|
|
/**
|
|
* A low profile banner with a message and 0 or more buttons
|
|
*/
|
|
export class InfoBanner implements Component<InfoBannerAttrs> {
|
|
view(vnode: Vnode<InfoBannerAttrs>): Children {
|
|
const { message, icon, helpLink, buttons, type } = vnode.attrs
|
|
// Adjust the top and bottom spacing because the buttons have a minimum height of 44px.
|
|
// This way the clickable area of the button overlaps with the text and the border a bit without having
|
|
// too much empty space
|
|
const buttonContainerStyle =
|
|
helpLink != null || buttons.length > 0
|
|
? {
|
|
marginTop: "-10px",
|
|
marginBottom: "-6px",
|
|
}
|
|
: undefined
|
|
return m(
|
|
".center-vertically.border-bottom.pr-4.pl-12.border-radius.mt-4",
|
|
{
|
|
style: {
|
|
border: `solid 2px ${type === BannerType.Warning ? theme.warning : theme.outline}`,
|
|
// keep the distance to the bottom of the banner the same in the case that buttons aren't present
|
|
minHeight: buttons.length > 0 ? undefined : px(37),
|
|
},
|
|
},
|
|
[
|
|
m(".mt-8.mr-8.abs", this.renderIcon(icon, type ?? null)), // absolute position makes the icon fixed to the top left corner of the banner
|
|
m(
|
|
"",
|
|
{ style: { "margin-left": px(size.icon_24 + 1) } }, // allow room for the icon
|
|
[
|
|
m(".mr-12.pt-8.pb-8", typeof message === "function" ? message() : m(".small.text-break", lang.get(message))),
|
|
m(".flex.ml-negative-8", { style: buttonContainerStyle }, [this.renderButtons(buttons), this.renderHelpLink(helpLink)]),
|
|
],
|
|
),
|
|
],
|
|
)
|
|
}
|
|
|
|
renderIcon(icon: AllIcons, type: BannerType | null): Children {
|
|
return m(Icon, {
|
|
icon,
|
|
style: {
|
|
fill: type === BannerType.Warning ? theme.warning : theme.on_surface_variant,
|
|
display: "block",
|
|
},
|
|
})
|
|
}
|
|
|
|
renderButtons(buttons: ReadonlyArray<BannerButtonAttrs | null>): Children {
|
|
if (buttons.length === 0) return null
|
|
return m(
|
|
".small.flex.row",
|
|
buttons.filter(isNotNull).map((attrs) => m(Button, { ...attrs, type: ButtonType.Secondary })),
|
|
)
|
|
}
|
|
|
|
renderHelpLink(helpLink?: InfoLink | null): Children | null {
|
|
if (helpLink == null) return null
|
|
|
|
return [
|
|
// Push the help button all the way to the right
|
|
m(".flex-grow"),
|
|
m(
|
|
".button-content",
|
|
{
|
|
style: {
|
|
marginRight: "-10px",
|
|
},
|
|
},
|
|
m(NavButton, {
|
|
icon: () => Icons.QuestionMark,
|
|
href: helpLink,
|
|
small: true,
|
|
hideLabel: true,
|
|
centred: true,
|
|
label: "help_label",
|
|
}),
|
|
),
|
|
]
|
|
}
|
|
}
|