index.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. import { unit } from '@ant-design/cssinjs';
  2. import { genFocusOutline, genFocusStyle, resetComponent, textEllipsis } from '../../style';
  3. import { genStyleHooks, mergeToken } from '../../theme/internal';
  4. // ============================== Mixins ==============================
  5. function getItemDisabledStyle(cls, token) {
  6. return {
  7. [`${cls}, ${cls}:hover, ${cls}:focus`]: {
  8. color: token.colorTextDisabled,
  9. cursor: 'not-allowed'
  10. }
  11. };
  12. }
  13. function getItemSelectedStyle(token) {
  14. return {
  15. backgroundColor: token.itemSelectedBg,
  16. boxShadow: token.boxShadowTertiary
  17. };
  18. }
  19. const segmentedTextEllipsisCss = Object.assign({
  20. overflow: 'hidden'
  21. }, textEllipsis);
  22. // ============================== Styles ==============================
  23. const genSegmentedStyle = token => {
  24. const {
  25. componentCls
  26. } = token;
  27. const labelHeight = token.calc(token.controlHeight).sub(token.calc(token.trackPadding).mul(2)).equal();
  28. const labelHeightLG = token.calc(token.controlHeightLG).sub(token.calc(token.trackPadding).mul(2)).equal();
  29. const labelHeightSM = token.calc(token.controlHeightSM).sub(token.calc(token.trackPadding).mul(2)).equal();
  30. return {
  31. [componentCls]: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, resetComponent(token)), {
  32. display: 'inline-block',
  33. padding: token.trackPadding,
  34. color: token.itemColor,
  35. background: token.trackBg,
  36. borderRadius: token.borderRadius,
  37. transition: `all ${token.motionDurationMid} ${token.motionEaseInOut}`
  38. }), genFocusStyle(token)), {
  39. [`${componentCls}-group`]: {
  40. position: 'relative',
  41. display: 'flex',
  42. alignItems: 'stretch',
  43. justifyItems: 'flex-start',
  44. flexDirection: 'row',
  45. width: '100%'
  46. },
  47. // RTL styles
  48. [`&${componentCls}-rtl`]: {
  49. direction: 'rtl'
  50. },
  51. [`&${componentCls}-vertical`]: {
  52. [`${componentCls}-group`]: {
  53. flexDirection: 'column'
  54. },
  55. [`${componentCls}-thumb`]: {
  56. width: '100%',
  57. height: 0,
  58. padding: `0 ${unit(token.paddingXXS)}`
  59. }
  60. },
  61. // block styles
  62. [`&${componentCls}-block`]: {
  63. display: 'flex'
  64. },
  65. [`&${componentCls}-block ${componentCls}-item`]: {
  66. flex: 1,
  67. minWidth: 0
  68. },
  69. // item styles
  70. [`${componentCls}-item`]: {
  71. position: 'relative',
  72. textAlign: 'center',
  73. cursor: 'pointer',
  74. transition: `color ${token.motionDurationMid} ${token.motionEaseInOut}`,
  75. borderRadius: token.borderRadiusSM,
  76. // Fix Safari render bug
  77. // https://github.com/ant-design/ant-design/issues/45250
  78. transform: 'translateZ(0)',
  79. '&-selected': Object.assign(Object.assign({}, getItemSelectedStyle(token)), {
  80. color: token.itemSelectedColor
  81. }),
  82. '&-focused': genFocusOutline(token),
  83. '&::after': {
  84. content: '""',
  85. position: 'absolute',
  86. zIndex: -1,
  87. width: '100%',
  88. height: '100%',
  89. top: 0,
  90. insetInlineStart: 0,
  91. borderRadius: 'inherit',
  92. opacity: 0,
  93. transition: `opacity ${token.motionDurationMid}`,
  94. // This is mandatory to make it not clickable or hoverable
  95. // Ref: https://github.com/ant-design/ant-design/issues/40888
  96. pointerEvents: 'none'
  97. },
  98. [`&:hover:not(${componentCls}-item-selected):not(${componentCls}-item-disabled)`]: {
  99. color: token.itemHoverColor,
  100. '&::after': {
  101. opacity: 1,
  102. backgroundColor: token.itemHoverBg
  103. }
  104. },
  105. [`&:active:not(${componentCls}-item-selected):not(${componentCls}-item-disabled)`]: {
  106. color: token.itemHoverColor,
  107. '&::after': {
  108. opacity: 1,
  109. backgroundColor: token.itemActiveBg
  110. }
  111. },
  112. '&-label': Object.assign({
  113. minHeight: labelHeight,
  114. lineHeight: unit(labelHeight),
  115. padding: `0 ${unit(token.segmentedPaddingHorizontal)}`
  116. }, segmentedTextEllipsisCss),
  117. // syntactic sugar to add `icon` for Segmented Item
  118. '&-icon + *': {
  119. marginInlineStart: token.calc(token.marginSM).div(2).equal()
  120. },
  121. '&-input': {
  122. position: 'absolute',
  123. insetBlockStart: 0,
  124. insetInlineStart: 0,
  125. width: 0,
  126. height: 0,
  127. opacity: 0,
  128. pointerEvents: 'none'
  129. }
  130. },
  131. // thumb styles
  132. [`${componentCls}-thumb`]: Object.assign(Object.assign({}, getItemSelectedStyle(token)), {
  133. position: 'absolute',
  134. insetBlockStart: 0,
  135. insetInlineStart: 0,
  136. width: 0,
  137. height: '100%',
  138. padding: `${unit(token.paddingXXS)} 0`,
  139. borderRadius: token.borderRadiusSM,
  140. transition: `transform ${token.motionDurationSlow} ${token.motionEaseInOut}, height ${token.motionDurationSlow} ${token.motionEaseInOut}`,
  141. [`& ~ ${componentCls}-item:not(${componentCls}-item-selected):not(${componentCls}-item-disabled)::after`]: {
  142. backgroundColor: 'transparent'
  143. }
  144. }),
  145. // size styles
  146. [`&${componentCls}-lg`]: {
  147. borderRadius: token.borderRadiusLG,
  148. [`${componentCls}-item-label`]: {
  149. minHeight: labelHeightLG,
  150. lineHeight: unit(labelHeightLG),
  151. padding: `0 ${unit(token.segmentedPaddingHorizontal)}`,
  152. fontSize: token.fontSizeLG
  153. },
  154. [`${componentCls}-item, ${componentCls}-thumb`]: {
  155. borderRadius: token.borderRadius
  156. }
  157. },
  158. [`&${componentCls}-sm`]: {
  159. borderRadius: token.borderRadiusSM,
  160. [`${componentCls}-item-label`]: {
  161. minHeight: labelHeightSM,
  162. lineHeight: unit(labelHeightSM),
  163. padding: `0 ${unit(token.segmentedPaddingHorizontalSM)}`
  164. },
  165. [`${componentCls}-item, ${componentCls}-thumb`]: {
  166. borderRadius: token.borderRadiusXS
  167. }
  168. }
  169. }), getItemDisabledStyle(`&-disabled ${componentCls}-item`, token)), getItemDisabledStyle(`${componentCls}-item-disabled`, token)), {
  170. // transition effect when `appear-active`
  171. [`${componentCls}-thumb-motion-appear-active`]: {
  172. transition: `transform ${token.motionDurationSlow} ${token.motionEaseInOut}, width ${token.motionDurationSlow} ${token.motionEaseInOut}`,
  173. willChange: 'transform, width'
  174. },
  175. [`&${componentCls}-shape-round`]: {
  176. borderRadius: 9999,
  177. [`${componentCls}-item, ${componentCls}-thumb`]: {
  178. borderRadius: 9999
  179. }
  180. }
  181. })
  182. };
  183. };
  184. // ============================== Export ==============================
  185. export const prepareComponentToken = token => {
  186. const {
  187. colorTextLabel,
  188. colorText,
  189. colorFillSecondary,
  190. colorBgElevated,
  191. colorFill,
  192. lineWidthBold,
  193. colorBgLayout
  194. } = token;
  195. return {
  196. trackPadding: lineWidthBold,
  197. trackBg: colorBgLayout,
  198. itemColor: colorTextLabel,
  199. itemHoverColor: colorText,
  200. itemHoverBg: colorFillSecondary,
  201. itemSelectedBg: colorBgElevated,
  202. itemActiveBg: colorFill,
  203. itemSelectedColor: colorText
  204. };
  205. };
  206. export default genStyleHooks('Segmented', token => {
  207. const {
  208. lineWidth,
  209. calc
  210. } = token;
  211. const segmentedToken = mergeToken(token, {
  212. segmentedPaddingHorizontal: calc(token.controlPaddingHorizontal).sub(lineWidth).equal(),
  213. segmentedPaddingHorizontalSM: calc(token.controlPaddingHorizontalSM).sub(lineWidth).equal()
  214. });
  215. return genSegmentedStyle(segmentedToken);
  216. }, prepareComponentToken);