index.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import { unit } from '@ant-design/cssinjs';
  2. import { genFocusOutline, resetComponent } from '../../style';
  3. import { genStyleHooks, mergeToken } from '../../theme/internal';
  4. // ============================== Styles ==============================
  5. export const genCheckboxStyle = token => {
  6. const {
  7. checkboxCls
  8. } = token;
  9. const wrapperCls = `${checkboxCls}-wrapper`;
  10. return [
  11. // ===================== Basic =====================
  12. {
  13. // Group
  14. [`${checkboxCls}-group`]: Object.assign(Object.assign({}, resetComponent(token)), {
  15. display: 'inline-flex',
  16. flexWrap: 'wrap',
  17. columnGap: token.marginXS,
  18. // Group > Grid
  19. [`> ${token.antCls}-row`]: {
  20. flex: 1
  21. }
  22. }),
  23. // Wrapper
  24. [wrapperCls]: Object.assign(Object.assign({}, resetComponent(token)), {
  25. display: 'inline-flex',
  26. alignItems: 'baseline',
  27. cursor: 'pointer',
  28. // Fix checkbox & radio in flex align #30260
  29. '&:after': {
  30. display: 'inline-block',
  31. width: 0,
  32. overflow: 'hidden',
  33. content: "'\\a0'"
  34. },
  35. // Checkbox near checkbox
  36. [`& + ${wrapperCls}`]: {
  37. marginInlineStart: 0
  38. },
  39. [`&${wrapperCls}-in-form-item`]: {
  40. 'input[type="checkbox"]': {
  41. width: 14,
  42. // FIXME: magic
  43. height: 14 // FIXME: magic
  44. }
  45. }
  46. }),
  47. // Wrapper > Checkbox
  48. [checkboxCls]: Object.assign(Object.assign({}, resetComponent(token)), {
  49. position: 'relative',
  50. whiteSpace: 'nowrap',
  51. lineHeight: 1,
  52. cursor: 'pointer',
  53. borderRadius: token.borderRadiusSM,
  54. // To make alignment right when `controlHeight` is changed
  55. // Ref: https://github.com/ant-design/ant-design/issues/41564
  56. alignSelf: 'center',
  57. // Wrapper > Checkbox > input
  58. [`${checkboxCls}-input`]: {
  59. position: 'absolute',
  60. // Since baseline align will get additional space offset,
  61. // we need to move input to top to make it align with text.
  62. // Ref: https://github.com/ant-design/ant-design/issues/38926#issuecomment-1486137799
  63. inset: 0,
  64. zIndex: 1,
  65. cursor: 'pointer',
  66. opacity: 0,
  67. margin: 0,
  68. [`&:focus-visible + ${checkboxCls}-inner`]: genFocusOutline(token)
  69. },
  70. // Wrapper > Checkbox > inner
  71. [`${checkboxCls}-inner`]: {
  72. boxSizing: 'border-box',
  73. display: 'block',
  74. width: token.checkboxSize,
  75. height: token.checkboxSize,
  76. direction: 'ltr',
  77. backgroundColor: token.colorBgContainer,
  78. border: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorder}`,
  79. borderRadius: token.borderRadiusSM,
  80. borderCollapse: 'separate',
  81. transition: `all ${token.motionDurationSlow}`,
  82. '&:after': {
  83. boxSizing: 'border-box',
  84. position: 'absolute',
  85. top: '50%',
  86. insetInlineStart: '25%',
  87. display: 'table',
  88. width: token.calc(token.checkboxSize).div(14).mul(5).equal(),
  89. height: token.calc(token.checkboxSize).div(14).mul(8).equal(),
  90. border: `${unit(token.lineWidthBold)} solid ${token.colorWhite}`,
  91. borderTop: 0,
  92. borderInlineStart: 0,
  93. transform: 'rotate(45deg) scale(0) translate(-50%,-50%)',
  94. opacity: 0,
  95. content: '""',
  96. transition: `all ${token.motionDurationFast} ${token.motionEaseInBack}, opacity ${token.motionDurationFast}`
  97. }
  98. },
  99. // Wrapper > Checkbox + Text
  100. '& + span': {
  101. paddingInlineStart: token.paddingXS,
  102. paddingInlineEnd: token.paddingXS
  103. }
  104. })
  105. },
  106. // ===================== Hover =====================
  107. {
  108. // Wrapper & Wrapper > Checkbox
  109. [`
  110. ${wrapperCls}:not(${wrapperCls}-disabled),
  111. ${checkboxCls}:not(${checkboxCls}-disabled)
  112. `]: {
  113. [`&:hover ${checkboxCls}-inner`]: {
  114. borderColor: token.colorPrimary
  115. }
  116. },
  117. [`${wrapperCls}:not(${wrapperCls}-disabled)`]: {
  118. [`&:hover ${checkboxCls}-checked:not(${checkboxCls}-disabled) ${checkboxCls}-inner`]: {
  119. backgroundColor: token.colorPrimaryHover,
  120. borderColor: 'transparent'
  121. },
  122. [`&:hover ${checkboxCls}-checked:not(${checkboxCls}-disabled):after`]: {
  123. borderColor: token.colorPrimaryHover
  124. }
  125. }
  126. },
  127. // ==================== Checked ====================
  128. {
  129. // Wrapper > Checkbox
  130. [`${checkboxCls}-checked`]: {
  131. [`${checkboxCls}-inner`]: {
  132. backgroundColor: token.colorPrimary,
  133. borderColor: token.colorPrimary,
  134. '&:after': {
  135. opacity: 1,
  136. transform: 'rotate(45deg) scale(1) translate(-50%,-50%)',
  137. transition: `all ${token.motionDurationMid} ${token.motionEaseOutBack} ${token.motionDurationFast}`
  138. }
  139. }
  140. },
  141. [`
  142. ${wrapperCls}-checked:not(${wrapperCls}-disabled),
  143. ${checkboxCls}-checked:not(${checkboxCls}-disabled)
  144. `]: {
  145. [`&:hover ${checkboxCls}-inner`]: {
  146. backgroundColor: token.colorPrimaryHover,
  147. borderColor: 'transparent'
  148. }
  149. }
  150. },
  151. // ================= Indeterminate =================
  152. {
  153. [checkboxCls]: {
  154. '&-indeterminate': {
  155. '&': {
  156. // Wrapper > Checkbox > inner
  157. [`${checkboxCls}-inner`]: {
  158. backgroundColor: `${token.colorBgContainer}`,
  159. borderColor: `${token.colorBorder}`,
  160. '&:after': {
  161. top: '50%',
  162. insetInlineStart: '50%',
  163. width: token.calc(token.fontSizeLG).div(2).equal(),
  164. height: token.calc(token.fontSizeLG).div(2).equal(),
  165. backgroundColor: token.colorPrimary,
  166. border: 0,
  167. transform: 'translate(-50%, -50%) scale(1)',
  168. opacity: 1,
  169. content: '""'
  170. }
  171. },
  172. // https://github.com/ant-design/ant-design/issues/50074
  173. [`&:hover ${checkboxCls}-inner`]: {
  174. backgroundColor: `${token.colorBgContainer}`,
  175. borderColor: `${token.colorPrimary}`
  176. }
  177. }
  178. }
  179. }
  180. },
  181. // ==================== Disable ====================
  182. {
  183. // Wrapper
  184. [`${wrapperCls}-disabled`]: {
  185. cursor: 'not-allowed'
  186. },
  187. // Wrapper > Checkbox
  188. [`${checkboxCls}-disabled`]: {
  189. // Wrapper > Checkbox > input
  190. [`&, ${checkboxCls}-input`]: {
  191. cursor: 'not-allowed',
  192. // Disabled for native input to enable Tooltip event handler
  193. // ref: https://github.com/ant-design/ant-design/issues/39822#issuecomment-1365075901
  194. pointerEvents: 'none'
  195. },
  196. // Wrapper > Checkbox > inner
  197. [`${checkboxCls}-inner`]: {
  198. background: token.colorBgContainerDisabled,
  199. borderColor: token.colorBorder,
  200. '&:after': {
  201. borderColor: token.colorTextDisabled
  202. }
  203. },
  204. '&:after': {
  205. display: 'none'
  206. },
  207. '& + span': {
  208. color: token.colorTextDisabled
  209. },
  210. [`&${checkboxCls}-indeterminate ${checkboxCls}-inner::after`]: {
  211. background: token.colorTextDisabled
  212. }
  213. }
  214. }];
  215. };
  216. // ============================== Export ==============================
  217. export function getStyle(prefixCls, token) {
  218. const checkboxToken = mergeToken(token, {
  219. checkboxCls: `.${prefixCls}`,
  220. checkboxSize: token.controlInteractiveSize
  221. });
  222. return genCheckboxStyle(checkboxToken);
  223. }
  224. export default genStyleHooks('Checkbox', (token, {
  225. prefixCls
  226. }) => [getStyle(prefixCls, token)]);