index.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import { Keyframes } from '../../_util/cssinjs';
  3. import { genComponentStyleHook, mergeToken } from '../../theme/internal';
  4. import { genFocusOutline, resetComponent } from '../../style';
  5. // ============================== Styles ==============================
  6. const antRadioEffect = new Keyframes('antRadioEffect', {
  7. '0%': {
  8. transform: 'scale(1)',
  9. opacity: 0.5
  10. },
  11. '100%': {
  12. transform: 'scale(1.6)',
  13. opacity: 0
  14. }
  15. });
  16. // styles from RadioGroup only
  17. const getGroupRadioStyle = token => {
  18. const {
  19. componentCls,
  20. antCls
  21. } = token;
  22. const groupPrefixCls = `${componentCls}-group`;
  23. return {
  24. [groupPrefixCls]: _extends(_extends({}, resetComponent(token)), {
  25. display: 'inline-block',
  26. fontSize: 0,
  27. // RTL
  28. [`&${groupPrefixCls}-rtl`]: {
  29. direction: 'rtl'
  30. },
  31. [`${antCls}-badge ${antCls}-badge-count`]: {
  32. zIndex: 1
  33. },
  34. [`> ${antCls}-badge:not(:first-child) > ${antCls}-button-wrapper`]: {
  35. borderInlineStart: 'none'
  36. }
  37. })
  38. };
  39. };
  40. // Styles from radio-wrapper
  41. const getRadioBasicStyle = token => {
  42. const {
  43. componentCls,
  44. radioWrapperMarginRight,
  45. radioCheckedColor,
  46. radioSize,
  47. motionDurationSlow,
  48. motionDurationMid,
  49. motionEaseInOut,
  50. motionEaseInOutCirc,
  51. radioButtonBg,
  52. colorBorder,
  53. lineWidth,
  54. radioDotSize,
  55. colorBgContainerDisabled,
  56. colorTextDisabled,
  57. paddingXS,
  58. radioDotDisabledColor,
  59. lineType,
  60. radioDotDisabledSize,
  61. wireframe,
  62. colorWhite
  63. } = token;
  64. const radioInnerPrefixCls = `${componentCls}-inner`;
  65. return {
  66. [`${componentCls}-wrapper`]: _extends(_extends({}, resetComponent(token)), {
  67. position: 'relative',
  68. display: 'inline-flex',
  69. alignItems: 'baseline',
  70. marginInlineStart: 0,
  71. marginInlineEnd: radioWrapperMarginRight,
  72. cursor: 'pointer',
  73. // RTL
  74. [`&${componentCls}-wrapper-rtl`]: {
  75. direction: 'rtl'
  76. },
  77. '&-disabled': {
  78. cursor: 'not-allowed',
  79. color: token.colorTextDisabled
  80. },
  81. '&::after': {
  82. display: 'inline-block',
  83. width: 0,
  84. overflow: 'hidden',
  85. content: '"\\a0"'
  86. },
  87. // hashId 在 wrapper 上,只能铺平
  88. [`${componentCls}-checked::after`]: {
  89. position: 'absolute',
  90. insetBlockStart: 0,
  91. insetInlineStart: 0,
  92. width: '100%',
  93. height: '100%',
  94. border: `${lineWidth}px ${lineType} ${radioCheckedColor}`,
  95. borderRadius: '50%',
  96. visibility: 'hidden',
  97. animationName: antRadioEffect,
  98. animationDuration: motionDurationSlow,
  99. animationTimingFunction: motionEaseInOut,
  100. animationFillMode: 'both',
  101. content: '""'
  102. },
  103. [componentCls]: _extends(_extends({}, resetComponent(token)), {
  104. position: 'relative',
  105. display: 'inline-block',
  106. outline: 'none',
  107. cursor: 'pointer',
  108. alignSelf: 'center'
  109. }),
  110. [`${componentCls}-wrapper:hover &,
  111. &:hover ${radioInnerPrefixCls}`]: {
  112. borderColor: radioCheckedColor
  113. },
  114. [`${componentCls}-input:focus-visible + ${radioInnerPrefixCls}`]: _extends({}, genFocusOutline(token)),
  115. [`${componentCls}:hover::after, ${componentCls}-wrapper:hover &::after`]: {
  116. visibility: 'visible'
  117. },
  118. [`${componentCls}-inner`]: {
  119. '&::after': {
  120. boxSizing: 'border-box',
  121. position: 'absolute',
  122. insetBlockStart: '50%',
  123. insetInlineStart: '50%',
  124. display: 'block',
  125. width: radioSize,
  126. height: radioSize,
  127. marginBlockStart: radioSize / -2,
  128. marginInlineStart: radioSize / -2,
  129. backgroundColor: wireframe ? radioCheckedColor : colorWhite,
  130. borderBlockStart: 0,
  131. borderInlineStart: 0,
  132. borderRadius: radioSize,
  133. transform: 'scale(0)',
  134. opacity: 0,
  135. transition: `all ${motionDurationSlow} ${motionEaseInOutCirc}`,
  136. content: '""'
  137. },
  138. boxSizing: 'border-box',
  139. position: 'relative',
  140. insetBlockStart: 0,
  141. insetInlineStart: 0,
  142. display: 'block',
  143. width: radioSize,
  144. height: radioSize,
  145. backgroundColor: radioButtonBg,
  146. borderColor: colorBorder,
  147. borderStyle: 'solid',
  148. borderWidth: lineWidth,
  149. borderRadius: '50%',
  150. transition: `all ${motionDurationMid}`
  151. },
  152. [`${componentCls}-input`]: {
  153. position: 'absolute',
  154. insetBlockStart: 0,
  155. insetInlineEnd: 0,
  156. insetBlockEnd: 0,
  157. insetInlineStart: 0,
  158. zIndex: 1,
  159. cursor: 'pointer',
  160. opacity: 0
  161. },
  162. // 选中状态
  163. [`${componentCls}-checked`]: {
  164. [radioInnerPrefixCls]: {
  165. borderColor: radioCheckedColor,
  166. backgroundColor: wireframe ? radioButtonBg : radioCheckedColor,
  167. '&::after': {
  168. transform: `scale(${radioDotSize / radioSize})`,
  169. opacity: 1,
  170. transition: `all ${motionDurationSlow} ${motionEaseInOutCirc}`
  171. }
  172. }
  173. },
  174. [`${componentCls}-disabled`]: {
  175. cursor: 'not-allowed',
  176. [radioInnerPrefixCls]: {
  177. backgroundColor: colorBgContainerDisabled,
  178. borderColor: colorBorder,
  179. cursor: 'not-allowed',
  180. '&::after': {
  181. backgroundColor: radioDotDisabledColor
  182. }
  183. },
  184. [`${componentCls}-input`]: {
  185. cursor: 'not-allowed'
  186. },
  187. [`${componentCls}-disabled + span`]: {
  188. color: colorTextDisabled,
  189. cursor: 'not-allowed'
  190. },
  191. [`&${componentCls}-checked`]: {
  192. [radioInnerPrefixCls]: {
  193. '&::after': {
  194. transform: `scale(${radioDotDisabledSize / radioSize})`
  195. }
  196. }
  197. }
  198. },
  199. [`span${componentCls} + *`]: {
  200. paddingInlineStart: paddingXS,
  201. paddingInlineEnd: paddingXS
  202. }
  203. })
  204. };
  205. };
  206. // Styles from radio-button
  207. const getRadioButtonStyle = token => {
  208. const {
  209. radioButtonColor,
  210. controlHeight,
  211. componentCls,
  212. lineWidth,
  213. lineType,
  214. colorBorder,
  215. motionDurationSlow,
  216. motionDurationMid,
  217. radioButtonPaddingHorizontal,
  218. fontSize,
  219. radioButtonBg,
  220. fontSizeLG,
  221. controlHeightLG,
  222. controlHeightSM,
  223. paddingXS,
  224. borderRadius,
  225. borderRadiusSM,
  226. borderRadiusLG,
  227. radioCheckedColor,
  228. radioButtonCheckedBg,
  229. radioButtonHoverColor,
  230. radioButtonActiveColor,
  231. radioSolidCheckedColor,
  232. colorTextDisabled,
  233. colorBgContainerDisabled,
  234. radioDisabledButtonCheckedColor,
  235. radioDisabledButtonCheckedBg
  236. } = token;
  237. return {
  238. [`${componentCls}-button-wrapper`]: {
  239. position: 'relative',
  240. display: 'inline-block',
  241. height: controlHeight,
  242. margin: 0,
  243. paddingInline: radioButtonPaddingHorizontal,
  244. paddingBlock: 0,
  245. color: radioButtonColor,
  246. fontSize,
  247. lineHeight: `${controlHeight - lineWidth * 2}px`,
  248. background: radioButtonBg,
  249. border: `${lineWidth}px ${lineType} ${colorBorder}`,
  250. // strange align fix for chrome but works
  251. // https://gw.alipayobjects.com/zos/rmsportal/VFTfKXJuogBAXcvfAUWJ.gif
  252. borderBlockStartWidth: lineWidth + 0.02,
  253. borderInlineStartWidth: 0,
  254. borderInlineEndWidth: lineWidth,
  255. cursor: 'pointer',
  256. transition: [`color ${motionDurationMid}`, `background ${motionDurationMid}`, `border-color ${motionDurationMid}`, `box-shadow ${motionDurationMid}`].join(','),
  257. a: {
  258. color: radioButtonColor
  259. },
  260. [`> ${componentCls}-button`]: {
  261. position: 'absolute',
  262. insetBlockStart: 0,
  263. insetInlineStart: 0,
  264. zIndex: -1,
  265. width: '100%',
  266. height: '100%'
  267. },
  268. '&:not(:first-child)': {
  269. '&::before': {
  270. position: 'absolute',
  271. insetBlockStart: -lineWidth,
  272. insetInlineStart: -lineWidth,
  273. display: 'block',
  274. boxSizing: 'content-box',
  275. width: 1,
  276. height: '100%',
  277. paddingBlock: lineWidth,
  278. paddingInline: 0,
  279. backgroundColor: colorBorder,
  280. transition: `background-color ${motionDurationSlow}`,
  281. content: '""'
  282. }
  283. },
  284. '&:first-child': {
  285. borderInlineStart: `${lineWidth}px ${lineType} ${colorBorder}`,
  286. borderStartStartRadius: borderRadius,
  287. borderEndStartRadius: borderRadius
  288. },
  289. '&:last-child': {
  290. borderStartEndRadius: borderRadius,
  291. borderEndEndRadius: borderRadius
  292. },
  293. '&:first-child:last-child': {
  294. borderRadius
  295. },
  296. [`${componentCls}-group-large &`]: {
  297. height: controlHeightLG,
  298. fontSize: fontSizeLG,
  299. lineHeight: `${controlHeightLG - lineWidth * 2}px`,
  300. '&:first-child': {
  301. borderStartStartRadius: borderRadiusLG,
  302. borderEndStartRadius: borderRadiusLG
  303. },
  304. '&:last-child': {
  305. borderStartEndRadius: borderRadiusLG,
  306. borderEndEndRadius: borderRadiusLG
  307. }
  308. },
  309. [`${componentCls}-group-small &`]: {
  310. height: controlHeightSM,
  311. paddingInline: paddingXS - lineWidth,
  312. paddingBlock: 0,
  313. lineHeight: `${controlHeightSM - lineWidth * 2}px`,
  314. '&:first-child': {
  315. borderStartStartRadius: borderRadiusSM,
  316. borderEndStartRadius: borderRadiusSM
  317. },
  318. '&:last-child': {
  319. borderStartEndRadius: borderRadiusSM,
  320. borderEndEndRadius: borderRadiusSM
  321. }
  322. },
  323. '&:hover': {
  324. position: 'relative',
  325. color: radioCheckedColor
  326. },
  327. '&:has(:focus-visible)': _extends({}, genFocusOutline(token)),
  328. [`${componentCls}-inner, input[type='checkbox'], input[type='radio']`]: {
  329. width: 0,
  330. height: 0,
  331. opacity: 0,
  332. pointerEvents: 'none'
  333. },
  334. [`&-checked:not(${componentCls}-button-wrapper-disabled)`]: {
  335. zIndex: 1,
  336. color: radioCheckedColor,
  337. background: radioButtonCheckedBg,
  338. borderColor: radioCheckedColor,
  339. '&::before': {
  340. backgroundColor: radioCheckedColor
  341. },
  342. '&:first-child': {
  343. borderColor: radioCheckedColor
  344. },
  345. '&:hover': {
  346. color: radioButtonHoverColor,
  347. borderColor: radioButtonHoverColor,
  348. '&::before': {
  349. backgroundColor: radioButtonHoverColor
  350. }
  351. },
  352. '&:active': {
  353. color: radioButtonActiveColor,
  354. borderColor: radioButtonActiveColor,
  355. '&::before': {
  356. backgroundColor: radioButtonActiveColor
  357. }
  358. }
  359. },
  360. [`${componentCls}-group-solid &-checked:not(${componentCls}-button-wrapper-disabled)`]: {
  361. color: radioSolidCheckedColor,
  362. background: radioCheckedColor,
  363. borderColor: radioCheckedColor,
  364. '&:hover': {
  365. color: radioSolidCheckedColor,
  366. background: radioButtonHoverColor,
  367. borderColor: radioButtonHoverColor
  368. },
  369. '&:active': {
  370. color: radioSolidCheckedColor,
  371. background: radioButtonActiveColor,
  372. borderColor: radioButtonActiveColor
  373. }
  374. },
  375. '&-disabled': {
  376. color: colorTextDisabled,
  377. backgroundColor: colorBgContainerDisabled,
  378. borderColor: colorBorder,
  379. cursor: 'not-allowed',
  380. '&:first-child, &:hover': {
  381. color: colorTextDisabled,
  382. backgroundColor: colorBgContainerDisabled,
  383. borderColor: colorBorder
  384. }
  385. },
  386. [`&-disabled${componentCls}-button-wrapper-checked`]: {
  387. color: radioDisabledButtonCheckedColor,
  388. backgroundColor: radioDisabledButtonCheckedBg,
  389. borderColor: colorBorder,
  390. boxShadow: 'none'
  391. }
  392. }
  393. };
  394. };
  395. // ============================== Export ==============================
  396. export default genComponentStyleHook('Radio', token => {
  397. const {
  398. padding,
  399. lineWidth,
  400. controlItemBgActiveDisabled,
  401. colorTextDisabled,
  402. colorBgContainer,
  403. fontSizeLG,
  404. controlOutline,
  405. colorPrimaryHover,
  406. colorPrimaryActive,
  407. colorText,
  408. colorPrimary,
  409. marginXS,
  410. controlOutlineWidth,
  411. colorTextLightSolid,
  412. wireframe
  413. } = token;
  414. // Radio
  415. const radioFocusShadow = `0 0 0 ${controlOutlineWidth}px ${controlOutline}`;
  416. const radioButtonFocusShadow = radioFocusShadow;
  417. const radioSize = fontSizeLG;
  418. const dotPadding = 4; // Fixed value
  419. const radioDotDisabledSize = radioSize - dotPadding * 2;
  420. const radioDotSize = wireframe ? radioDotDisabledSize : radioSize - (dotPadding + lineWidth) * 2;
  421. const radioCheckedColor = colorPrimary;
  422. // Radio buttons
  423. const radioButtonColor = colorText;
  424. const radioButtonHoverColor = colorPrimaryHover;
  425. const radioButtonActiveColor = colorPrimaryActive;
  426. const radioButtonPaddingHorizontal = padding - lineWidth;
  427. const radioDisabledButtonCheckedColor = colorTextDisabled;
  428. const radioWrapperMarginRight = marginXS;
  429. const radioToken = mergeToken(token, {
  430. radioFocusShadow,
  431. radioButtonFocusShadow,
  432. radioSize,
  433. radioDotSize,
  434. radioDotDisabledSize,
  435. radioCheckedColor,
  436. radioDotDisabledColor: colorTextDisabled,
  437. radioSolidCheckedColor: colorTextLightSolid,
  438. radioButtonBg: colorBgContainer,
  439. radioButtonCheckedBg: colorBgContainer,
  440. radioButtonColor,
  441. radioButtonHoverColor,
  442. radioButtonActiveColor,
  443. radioButtonPaddingHorizontal,
  444. radioDisabledButtonCheckedBg: controlItemBgActiveDisabled,
  445. radioDisabledButtonCheckedColor,
  446. radioWrapperMarginRight
  447. });
  448. return [getGroupRadioStyle(radioToken), getRadioBasicStyle(radioToken), getRadioButtonStyle(radioToken)];
  449. });