UNPKG

@kiwicom/orbit-components

Version:

Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.

261 lines (250 loc) 8.72 kB
import * as React from "react"; import styled, { css } from "styled-components"; import defaultTheme from "../defaultTheme"; import InformationCircle from "../icons/InformationCircle"; import Check from "../icons/Check"; import AlertTriangle from "../icons/Alert"; import AlertCircle from "../icons/AlertCircle"; import Close from "../icons/Close"; import ButtonLink from "../ButtonLink"; import { StyledTextLink } from "../TextLink"; import { TYPE_OPTIONS, TOKENS, CLOSE_BUTTON_DATA_TEST } from "./consts"; import { rtlSpacing, right } from "../utils/rtl"; import getSpacingToken from "../common/getSpacingToken"; import { Item } from "../List/ListItem"; import { StyledText } from "../Text"; import useTranslate from "../hooks/useTranslate"; import { StyledHeading } from "../Heading"; import media from "../utils/mediaQuery"; const getTypeToken = name => ({ theme, type }) => { const tokens = { [TOKENS.colorIconAlert]: { [TYPE_OPTIONS.INFO]: theme.orbit.paletteBlueDarker, [TYPE_OPTIONS.SUCCESS]: theme.orbit.paletteGreenDarker, [TYPE_OPTIONS.WARNING]: theme.orbit.paletteOrangeDarker, [TYPE_OPTIONS.CRITICAL]: theme.orbit.paletteRedDarker }, [TOKENS.backgroundAlert]: { [TYPE_OPTIONS.INFO]: theme.orbit.backgroundAlertInfo, [TYPE_OPTIONS.SUCCESS]: theme.orbit.backgroundAlertSuccess, [TYPE_OPTIONS.WARNING]: theme.orbit.backgroundAlertWarning, [TYPE_OPTIONS.CRITICAL]: theme.orbit.backgroundAlertCritical }, [TOKENS.colorTextAlert]: { [TYPE_OPTIONS.INFO]: theme.orbit.colorTextAlertInfo, [TYPE_OPTIONS.SUCCESS]: theme.orbit.colorTextAlertSuccess, [TYPE_OPTIONS.WARNING]: theme.orbit.colorTextAlertWarning, [TYPE_OPTIONS.CRITICAL]: theme.orbit.colorTextAlertCritical }, // TODO: create token [TOKENS.colorTextLinkAlertHover]: { [TYPE_OPTIONS.INFO]: theme.orbit.paletteBlueDarkHover, [TYPE_OPTIONS.SUCCESS]: theme.orbit.paletteGreenDarkHover, [TYPE_OPTIONS.WARNING]: theme.orbit.paletteOrangeDarkHover, [TYPE_OPTIONS.CRITICAL]: theme.orbit.paletteRedDarkActive }, [TOKENS.colorBorderAlert]: { [TYPE_OPTIONS.INFO]: theme.orbit.paletteBlueLightHover, [TYPE_OPTIONS.SUCCESS]: theme.orbit.paletteGreenLightHover, [TYPE_OPTIONS.WARNING]: theme.orbit.paletteOrangeLightHover, [TYPE_OPTIONS.CRITICAL]: theme.orbit.paletteRedLightHover } }; return tokens[name][type]; }; const Icon = ({ icon, type }) => { // Icon should be boolean and TRUE if (typeof icon === "boolean" && icon) { if (type === TYPE_OPTIONS.INFO) { return React.createElement(InformationCircle, null); } if (type === TYPE_OPTIONS.SUCCESS) { return React.createElement(Check, null); } if (type === TYPE_OPTIONS.WARNING) { return React.createElement(AlertTriangle, null); } if (type === TYPE_OPTIONS.CRITICAL) { return React.createElement(AlertCircle, null); } } return icon; }; const StyledDiv = ({ className, children, dataTest }) => React.createElement("div", { className: className, "data-test": dataTest }, children); const StyledAlert = styled(StyledDiv).withConfig({ displayName: "Alert__StyledAlert", componentId: "svgppc-0" })(["position:relative;display:flex;width:100%;border-radius:", ";border:1px solid ", ";background:", ";color:", ";font-family:", ";font-size:", ";line-height:", ";box-sizing:border-box;margin-bottom:", ";padding:", ";", ""], ({ theme }) => theme.orbit.borderRadiusNormal, getTypeToken(TOKENS.colorBorderAlert), getTypeToken(TOKENS.backgroundAlert), getTypeToken(TOKENS.colorTextAlert), ({ theme }) => theme.orbit.fontFamily, ({ theme }) => theme.orbit.fontSizeTextNormal, ({ theme }) => theme.orbit.lineHeightTextNormal, getSpacingToken, ({ theme, closable }) => closable ? rtlSpacing(`${theme.orbit.spaceXSmall} ${theme.orbit.spaceXLarge} ${theme.orbit.spaceXSmall} ${theme.orbit.spaceXSmall}`) : theme.orbit.spaceXSmall, media.tablet(css(["padding:", ";"], ({ theme, closable }) => closable ? rtlSpacing(`${theme.orbit.paddingAlert} ${theme.orbit.spaceXXLarge} ${theme.orbit.paddingAlert} ${theme.orbit.paddingAlert}`) : theme.orbit.paddingAlert))); StyledAlert.defaultProps = { theme: defaultTheme }; const IconContainer = styled(StyledDiv).withConfig({ displayName: "Alert__IconContainer", componentId: "svgppc-1" })(["flex-shrink:0;margin:", ";color:", ";display:", ";align-items:", ";", ""], ({ theme }) => rtlSpacing(`0 ${theme.orbit.spaceXSmall} 0 0`), getTypeToken(TOKENS.colorIconAlert), ({ inlineActions }) => inlineActions && "flex", ({ inlineActions }) => inlineActions && "center", media.tablet(css(["margin:", ";"], ({ theme }) => rtlSpacing(`0 ${theme.orbit.spaceSmall} 0 0`)))); IconContainer.defaultProps = { theme: defaultTheme }; const ContentWrapper = styled(StyledDiv).withConfig({ displayName: "Alert__ContentWrapper", componentId: "svgppc-2" })(["flex:1;display:flex;flex-direction:", ";align-items:", ";justify-content:", ";"], ({ title, inlineActions }) => title && (inlineActions ? "row" : "column"), ({ title }) => !title && "center", ({ inlineActions }) => inlineActions && "space-between"); const Title = styled(StyledDiv).withConfig({ displayName: "Alert__Title", componentId: "svgppc-3" })(["color:", ";display:flex;align-items:center;margin-bottom:", ";font-weight:", ";line-height:", ";min-height:", ";", ""], getTypeToken(TOKENS.colorIconAlert), ({ theme, hasChildren, inlineActions }) => hasChildren && (inlineActions ? "0" : theme.orbit.spaceXXSmall), ({ theme }) => theme.orbit.fontWeightBold, ({ theme }) => theme.orbit.lineHeightHeading, ({ theme }) => theme.orbit.heightIconMedium, media.tablet(css(["margin-bottom:", ";"], ({ theme, hasChildren, inlineActions }) => hasChildren && (inlineActions ? "0" : theme.orbit.spaceXSmall)))); Title.defaultProps = { theme: defaultTheme }; const Content = styled(StyledDiv).withConfig({ displayName: "Alert__Content", componentId: "svgppc-4" })(["display:block;width:", ";& a,& ", "{color:", ";font-weight:", ";transition:color ", " ease-in-out;&:hover,&:focus,&:active{color:", ";}}& ", ",", ",", "{color:", ";}"], ({ inlineActions }) => !inlineActions && "100%", StyledTextLink, getTypeToken(TOKENS.colorTextAlert), ({ theme }) => theme.orbit.fontWeightMedium, ({ theme }) => theme.orbit.durationFast, getTypeToken(TOKENS.colorTextLinkAlertHover), Item, StyledText, StyledHeading, getTypeToken(TOKENS.colorTextAlert)); Content.defaultProps = { theme: defaultTheme }; const CloseContainer = styled(StyledDiv).withConfig({ displayName: "Alert__CloseContainer", componentId: "svgppc-5" })(["position:absolute;top:", ";margin-top:", ";", ":0;margin-", ":", ";"], ({ hasChildren }) => hasChildren ? 0 : "50%", ({ hasChildren, theme }) => !hasChildren && `-${theme.orbit.widthIconSmall}`, right, right, ({ hasChildren, theme }) => !hasChildren && theme.orbit.spaceXSmall); CloseContainer.defaultProps = { theme: defaultTheme }; const AlertCloseButton = ({ hasChildren, dataTest, onClick, icon }) => { const translate = useTranslate(); return React.createElement(CloseContainer, { hasChildren: hasChildren }, React.createElement(ButtonLink, { dataTest: dataTest, onClick: onClick, size: "small", icon: icon, type: "secondary", transparent: true, title: translate("button_close") })); }; const Alert = props => { const { type = TYPE_OPTIONS.INFO, title, closable, icon, onClose = () => {}, children, dataTest, spaceAfter, inlineActions = false } = props; return React.createElement(StyledAlert, { type: type, icon: icon, closable: closable, dataTest: dataTest, spaceAfter: spaceAfter }, icon && React.createElement(IconContainer, { type: type, inlineActions: inlineActions }, React.createElement(Icon, { type: type, icon: icon })), React.createElement(ContentWrapper, { title: title, inlineActions: inlineActions }, title && React.createElement(Title, { type: type, hasChildren: children, inlineActions: inlineActions }, title), children && !inlineActions && React.createElement(Content, { title: title, type: type }, children), inlineActions && React.createElement(Content, { title: title, type: type, inlineActions: inlineActions }, inlineActions)), closable && React.createElement(AlertCloseButton, { hasChildren: children, dataTest: CLOSE_BUTTON_DATA_TEST, onClick: onClose, icon: React.createElement(Close, { size: "small", color: type }) })); }; export default Alert;