index.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. import { Keyframes, unit } from '@ant-design/cssinjs';
  2. import { CONTAINER_MAX_OFFSET } from '../../_util/hooks/useZIndex';
  3. import { genFocusStyle, resetComponent } from '../../style';
  4. import { genStyleHooks, mergeToken } from '../../theme/internal';
  5. import genNotificationPlacementStyle from './placement';
  6. import genStackStyle from './stack';
  7. export const genNoticeStyle = token => {
  8. const {
  9. iconCls,
  10. componentCls,
  11. // .ant-notification
  12. boxShadow,
  13. fontSizeLG,
  14. notificationMarginBottom,
  15. borderRadiusLG,
  16. colorSuccess,
  17. colorInfo,
  18. colorWarning,
  19. colorError,
  20. colorTextHeading,
  21. notificationBg,
  22. notificationPadding,
  23. notificationMarginEdge,
  24. notificationProgressBg,
  25. notificationProgressHeight,
  26. fontSize,
  27. lineHeight,
  28. width,
  29. notificationIconSize,
  30. colorText
  31. } = token;
  32. const noticeCls = `${componentCls}-notice`;
  33. return {
  34. position: 'relative',
  35. marginBottom: notificationMarginBottom,
  36. marginInlineStart: 'auto',
  37. background: notificationBg,
  38. borderRadius: borderRadiusLG,
  39. boxShadow,
  40. [noticeCls]: {
  41. padding: notificationPadding,
  42. width,
  43. maxWidth: `calc(100vw - ${unit(token.calc(notificationMarginEdge).mul(2).equal())})`,
  44. overflow: 'hidden',
  45. lineHeight,
  46. wordWrap: 'break-word'
  47. },
  48. [`${noticeCls}-message`]: {
  49. color: colorTextHeading,
  50. fontSize: fontSizeLG,
  51. lineHeight: token.lineHeightLG
  52. },
  53. [`${noticeCls}-description`]: {
  54. fontSize,
  55. color: colorText,
  56. marginTop: token.marginXS
  57. },
  58. [`${noticeCls}-closable ${noticeCls}-message`]: {
  59. paddingInlineEnd: token.paddingLG
  60. },
  61. [`${noticeCls}-with-icon ${noticeCls}-message`]: {
  62. marginInlineStart: token.calc(token.marginSM).add(notificationIconSize).equal(),
  63. fontSize: fontSizeLG
  64. },
  65. [`${noticeCls}-with-icon ${noticeCls}-description`]: {
  66. marginInlineStart: token.calc(token.marginSM).add(notificationIconSize).equal(),
  67. fontSize
  68. },
  69. // Icon & color style in different selector level
  70. // https://github.com/ant-design/ant-design/issues/16503
  71. // https://github.com/ant-design/ant-design/issues/15512
  72. [`${noticeCls}-icon`]: {
  73. position: 'absolute',
  74. fontSize: notificationIconSize,
  75. lineHeight: 1,
  76. // icon-font
  77. [`&-success${iconCls}`]: {
  78. color: colorSuccess
  79. },
  80. [`&-info${iconCls}`]: {
  81. color: colorInfo
  82. },
  83. [`&-warning${iconCls}`]: {
  84. color: colorWarning
  85. },
  86. [`&-error${iconCls}`]: {
  87. color: colorError
  88. }
  89. },
  90. [`${noticeCls}-close`]: Object.assign({
  91. position: 'absolute',
  92. top: token.notificationPaddingVertical,
  93. insetInlineEnd: token.notificationPaddingHorizontal,
  94. color: token.colorIcon,
  95. outline: 'none',
  96. width: token.notificationCloseButtonSize,
  97. height: token.notificationCloseButtonSize,
  98. borderRadius: token.borderRadiusSM,
  99. transition: `background-color ${token.motionDurationMid}, color ${token.motionDurationMid}`,
  100. display: 'flex',
  101. alignItems: 'center',
  102. justifyContent: 'center',
  103. background: 'none',
  104. border: 'none',
  105. '&:hover': {
  106. color: token.colorIconHover,
  107. backgroundColor: token.colorBgTextHover
  108. },
  109. '&:active': {
  110. backgroundColor: token.colorBgTextActive
  111. }
  112. }, genFocusStyle(token)),
  113. [`${noticeCls}-progress`]: {
  114. position: 'absolute',
  115. display: 'block',
  116. appearance: 'none',
  117. inlineSize: `calc(100% - ${unit(borderRadiusLG)} * 2)`,
  118. left: {
  119. _skip_check_: true,
  120. value: borderRadiusLG
  121. },
  122. right: {
  123. _skip_check_: true,
  124. value: borderRadiusLG
  125. },
  126. bottom: 0,
  127. blockSize: notificationProgressHeight,
  128. border: 0,
  129. '&, &::-webkit-progress-bar': {
  130. borderRadius: borderRadiusLG,
  131. backgroundColor: `rgba(0, 0, 0, 0.04)`
  132. },
  133. '&::-moz-progress-bar': {
  134. background: notificationProgressBg
  135. },
  136. '&::-webkit-progress-value': {
  137. borderRadius: borderRadiusLG,
  138. background: notificationProgressBg
  139. }
  140. },
  141. [`${noticeCls}-actions`]: {
  142. float: 'right',
  143. marginTop: token.marginSM
  144. }
  145. };
  146. };
  147. const genNotificationStyle = token => {
  148. const {
  149. componentCls,
  150. // .ant-notification
  151. notificationMarginBottom,
  152. notificationMarginEdge,
  153. motionDurationMid,
  154. motionEaseInOut
  155. } = token;
  156. const noticeCls = `${componentCls}-notice`;
  157. const fadeOut = new Keyframes('antNotificationFadeOut', {
  158. '0%': {
  159. maxHeight: token.animationMaxHeight,
  160. marginBottom: notificationMarginBottom
  161. },
  162. '100%': {
  163. maxHeight: 0,
  164. marginBottom: 0,
  165. paddingTop: 0,
  166. paddingBottom: 0,
  167. opacity: 0
  168. }
  169. });
  170. return [
  171. // ============================ Holder ============================
  172. {
  173. [componentCls]: Object.assign(Object.assign({}, resetComponent(token)), {
  174. position: 'fixed',
  175. zIndex: token.zIndexPopup,
  176. marginRight: {
  177. value: notificationMarginEdge,
  178. _skip_check_: true
  179. },
  180. [`${componentCls}-hook-holder`]: {
  181. position: 'relative'
  182. },
  183. // animation
  184. [`${componentCls}-fade-appear-prepare`]: {
  185. opacity: '0 !important'
  186. },
  187. [`${componentCls}-fade-enter, ${componentCls}-fade-appear`]: {
  188. animationDuration: token.motionDurationMid,
  189. animationTimingFunction: motionEaseInOut,
  190. animationFillMode: 'both',
  191. opacity: 0,
  192. animationPlayState: 'paused'
  193. },
  194. [`${componentCls}-fade-leave`]: {
  195. animationTimingFunction: motionEaseInOut,
  196. animationFillMode: 'both',
  197. animationDuration: motionDurationMid,
  198. animationPlayState: 'paused'
  199. },
  200. [`${componentCls}-fade-enter${componentCls}-fade-enter-active, ${componentCls}-fade-appear${componentCls}-fade-appear-active`]: {
  201. animationPlayState: 'running'
  202. },
  203. [`${componentCls}-fade-leave${componentCls}-fade-leave-active`]: {
  204. animationName: fadeOut,
  205. animationPlayState: 'running'
  206. },
  207. // RTL
  208. '&-rtl': {
  209. direction: 'rtl',
  210. [`${noticeCls}-actions`]: {
  211. float: 'left'
  212. }
  213. }
  214. })
  215. },
  216. // ============================ Notice ============================
  217. {
  218. [componentCls]: {
  219. [`${noticeCls}-wrapper`]: Object.assign({}, genNoticeStyle(token))
  220. }
  221. }];
  222. };
  223. // ============================== Export ==============================
  224. export const prepareComponentToken = token => ({
  225. zIndexPopup: token.zIndexPopupBase + CONTAINER_MAX_OFFSET + 50,
  226. width: 384
  227. });
  228. export const prepareNotificationToken = token => {
  229. const notificationPaddingVertical = token.paddingMD;
  230. const notificationPaddingHorizontal = token.paddingLG;
  231. const notificationToken = mergeToken(token, {
  232. notificationBg: token.colorBgElevated,
  233. notificationPaddingVertical,
  234. notificationPaddingHorizontal,
  235. notificationIconSize: token.calc(token.fontSizeLG).mul(token.lineHeightLG).equal(),
  236. notificationCloseButtonSize: token.calc(token.controlHeightLG).mul(0.55).equal(),
  237. notificationMarginBottom: token.margin,
  238. notificationPadding: `${unit(token.paddingMD)} ${unit(token.paddingContentHorizontalLG)}`,
  239. notificationMarginEdge: token.marginLG,
  240. animationMaxHeight: 150,
  241. notificationStackLayer: 3,
  242. notificationProgressHeight: 2,
  243. notificationProgressBg: `linear-gradient(90deg, ${token.colorPrimaryBorderHover}, ${token.colorPrimary})`
  244. });
  245. return notificationToken;
  246. };
  247. export default genStyleHooks('Notification', token => {
  248. const notificationToken = prepareNotificationToken(token);
  249. return [genNotificationStyle(notificationToken), genNotificationPlacementStyle(notificationToken), genStackStyle(notificationToken)];
  250. }, prepareComponentToken);