index.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. import { unit } from '@ant-design/cssinjs';
  2. import { genFocusOutline, genFocusStyle, resetComponent, textEllipsis } from '../../style';
  3. import { genStyleHooks, mergeToken } from '../../theme/internal';
  4. import genMotionStyle from './motion';
  5. const genCardStyle = token => {
  6. const {
  7. componentCls,
  8. tabsCardPadding,
  9. cardBg,
  10. cardGutter,
  11. colorBorderSecondary,
  12. itemSelectedColor
  13. } = token;
  14. return {
  15. [`${componentCls}-card`]: {
  16. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  17. [`${componentCls}-tab`]: {
  18. margin: 0,
  19. padding: tabsCardPadding,
  20. background: cardBg,
  21. border: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
  22. transition: `all ${token.motionDurationSlow} ${token.motionEaseInOut}`
  23. },
  24. [`${componentCls}-tab-active`]: {
  25. color: itemSelectedColor,
  26. background: token.colorBgContainer
  27. },
  28. [`${componentCls}-tab-focus:has(${componentCls}-tab-btn:focus-visible)`]: genFocusOutline(token, -3),
  29. [`& ${componentCls}-tab${componentCls}-tab-focus ${componentCls}-tab-btn:focus-visible`]: {
  30. outline: 'none'
  31. },
  32. [`${componentCls}-ink-bar`]: {
  33. visibility: 'hidden'
  34. }
  35. },
  36. // ========================== Top & Bottom ==========================
  37. [`&${componentCls}-top, &${componentCls}-bottom`]: {
  38. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  39. [`${componentCls}-tab + ${componentCls}-tab`]: {
  40. marginLeft: {
  41. _skip_check_: true,
  42. value: unit(cardGutter)
  43. }
  44. }
  45. }
  46. },
  47. [`&${componentCls}-top`]: {
  48. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  49. [`${componentCls}-tab`]: {
  50. borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0`
  51. },
  52. [`${componentCls}-tab-active`]: {
  53. borderBottomColor: token.colorBgContainer
  54. }
  55. }
  56. },
  57. [`&${componentCls}-bottom`]: {
  58. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  59. [`${componentCls}-tab`]: {
  60. borderRadius: `0 0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)}`
  61. },
  62. [`${componentCls}-tab-active`]: {
  63. borderTopColor: token.colorBgContainer
  64. }
  65. }
  66. },
  67. // ========================== Left & Right ==========================
  68. [`&${componentCls}-left, &${componentCls}-right`]: {
  69. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  70. [`${componentCls}-tab + ${componentCls}-tab`]: {
  71. marginTop: unit(cardGutter)
  72. }
  73. }
  74. },
  75. [`&${componentCls}-left`]: {
  76. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  77. [`${componentCls}-tab`]: {
  78. borderRadius: {
  79. _skip_check_: true,
  80. value: `${unit(token.borderRadiusLG)} 0 0 ${unit(token.borderRadiusLG)}`
  81. }
  82. },
  83. [`${componentCls}-tab-active`]: {
  84. borderRightColor: {
  85. _skip_check_: true,
  86. value: token.colorBgContainer
  87. }
  88. }
  89. }
  90. },
  91. [`&${componentCls}-right`]: {
  92. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  93. [`${componentCls}-tab`]: {
  94. borderRadius: {
  95. _skip_check_: true,
  96. value: `0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0`
  97. }
  98. },
  99. [`${componentCls}-tab-active`]: {
  100. borderLeftColor: {
  101. _skip_check_: true,
  102. value: token.colorBgContainer
  103. }
  104. }
  105. }
  106. }
  107. }
  108. };
  109. };
  110. const genDropdownStyle = token => {
  111. const {
  112. componentCls,
  113. itemHoverColor,
  114. dropdownEdgeChildVerticalPadding
  115. } = token;
  116. return {
  117. [`${componentCls}-dropdown`]: Object.assign(Object.assign({}, resetComponent(token)), {
  118. position: 'absolute',
  119. top: -9999,
  120. left: {
  121. _skip_check_: true,
  122. value: -9999
  123. },
  124. zIndex: token.zIndexPopup,
  125. display: 'block',
  126. '&-hidden': {
  127. display: 'none'
  128. },
  129. [`${componentCls}-dropdown-menu`]: {
  130. maxHeight: token.tabsDropdownHeight,
  131. margin: 0,
  132. padding: `${unit(dropdownEdgeChildVerticalPadding)} 0`,
  133. overflowX: 'hidden',
  134. overflowY: 'auto',
  135. textAlign: {
  136. _skip_check_: true,
  137. value: 'left'
  138. },
  139. listStyleType: 'none',
  140. backgroundColor: token.colorBgContainer,
  141. backgroundClip: 'padding-box',
  142. borderRadius: token.borderRadiusLG,
  143. outline: 'none',
  144. boxShadow: token.boxShadowSecondary,
  145. '&-item': Object.assign(Object.assign({}, textEllipsis), {
  146. display: 'flex',
  147. alignItems: 'center',
  148. minWidth: token.tabsDropdownWidth,
  149. margin: 0,
  150. padding: `${unit(token.paddingXXS)} ${unit(token.paddingSM)}`,
  151. color: token.colorText,
  152. fontWeight: 'normal',
  153. fontSize: token.fontSize,
  154. lineHeight: token.lineHeight,
  155. cursor: 'pointer',
  156. transition: `all ${token.motionDurationSlow}`,
  157. '> span': {
  158. flex: 1,
  159. whiteSpace: 'nowrap'
  160. },
  161. '&-remove': {
  162. flex: 'none',
  163. marginLeft: {
  164. _skip_check_: true,
  165. value: token.marginSM
  166. },
  167. color: token.colorIcon,
  168. fontSize: token.fontSizeSM,
  169. background: 'transparent',
  170. border: 0,
  171. cursor: 'pointer',
  172. '&:hover': {
  173. color: itemHoverColor
  174. }
  175. },
  176. '&:hover': {
  177. background: token.controlItemBgHover
  178. },
  179. '&-disabled': {
  180. '&, &:hover': {
  181. color: token.colorTextDisabled,
  182. background: 'transparent',
  183. cursor: 'not-allowed'
  184. }
  185. }
  186. })
  187. }
  188. })
  189. };
  190. };
  191. const genPositionStyle = token => {
  192. const {
  193. componentCls,
  194. margin,
  195. colorBorderSecondary,
  196. horizontalMargin,
  197. verticalItemPadding,
  198. verticalItemMargin,
  199. calc
  200. } = token;
  201. return {
  202. // ========================== Top & Bottom ==========================
  203. [`${componentCls}-top, ${componentCls}-bottom`]: {
  204. flexDirection: 'column',
  205. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  206. margin: horizontalMargin,
  207. '&::before': {
  208. position: 'absolute',
  209. right: {
  210. _skip_check_: true,
  211. value: 0
  212. },
  213. left: {
  214. _skip_check_: true,
  215. value: 0
  216. },
  217. borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
  218. content: "''"
  219. },
  220. [`${componentCls}-ink-bar`]: {
  221. height: token.lineWidthBold,
  222. '&-animated': {
  223. transition: `width ${token.motionDurationSlow}, left ${token.motionDurationSlow},
  224. right ${token.motionDurationSlow}`
  225. }
  226. },
  227. [`${componentCls}-nav-wrap`]: {
  228. '&::before, &::after': {
  229. top: 0,
  230. bottom: 0,
  231. width: token.controlHeight
  232. },
  233. '&::before': {
  234. left: {
  235. _skip_check_: true,
  236. value: 0
  237. },
  238. boxShadow: token.boxShadowTabsOverflowLeft
  239. },
  240. '&::after': {
  241. right: {
  242. _skip_check_: true,
  243. value: 0
  244. },
  245. boxShadow: token.boxShadowTabsOverflowRight
  246. },
  247. [`&${componentCls}-nav-wrap-ping-left::before`]: {
  248. opacity: 1
  249. },
  250. [`&${componentCls}-nav-wrap-ping-right::after`]: {
  251. opacity: 1
  252. }
  253. }
  254. }
  255. },
  256. [`${componentCls}-top`]: {
  257. [`> ${componentCls}-nav,
  258. > div > ${componentCls}-nav`]: {
  259. '&::before': {
  260. bottom: 0
  261. },
  262. [`${componentCls}-ink-bar`]: {
  263. bottom: 0
  264. }
  265. }
  266. },
  267. [`${componentCls}-bottom`]: {
  268. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  269. order: 1,
  270. marginTop: margin,
  271. marginBottom: 0,
  272. '&::before': {
  273. top: 0
  274. },
  275. [`${componentCls}-ink-bar`]: {
  276. top: 0
  277. }
  278. },
  279. [`> ${componentCls}-content-holder, > div > ${componentCls}-content-holder`]: {
  280. order: 0
  281. }
  282. },
  283. // ========================== Left & Right ==========================
  284. [`${componentCls}-left, ${componentCls}-right`]: {
  285. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  286. flexDirection: 'column',
  287. minWidth: calc(token.controlHeight).mul(1.25).equal(),
  288. // >>>>>>>>>>> Tab
  289. [`${componentCls}-tab`]: {
  290. padding: verticalItemPadding,
  291. textAlign: 'center'
  292. },
  293. [`${componentCls}-tab + ${componentCls}-tab`]: {
  294. margin: verticalItemMargin
  295. },
  296. // >>>>>>>>>>> Nav
  297. [`${componentCls}-nav-wrap`]: {
  298. flexDirection: 'column',
  299. '&::before, &::after': {
  300. right: {
  301. _skip_check_: true,
  302. value: 0
  303. },
  304. left: {
  305. _skip_check_: true,
  306. value: 0
  307. },
  308. height: token.controlHeight
  309. },
  310. '&::before': {
  311. top: 0,
  312. boxShadow: token.boxShadowTabsOverflowTop
  313. },
  314. '&::after': {
  315. bottom: 0,
  316. boxShadow: token.boxShadowTabsOverflowBottom
  317. },
  318. [`&${componentCls}-nav-wrap-ping-top::before`]: {
  319. opacity: 1
  320. },
  321. [`&${componentCls}-nav-wrap-ping-bottom::after`]: {
  322. opacity: 1
  323. }
  324. },
  325. // >>>>>>>>>>> Ink Bar
  326. [`${componentCls}-ink-bar`]: {
  327. width: token.lineWidthBold,
  328. '&-animated': {
  329. transition: `height ${token.motionDurationSlow}, top ${token.motionDurationSlow}`
  330. }
  331. },
  332. [`${componentCls}-nav-list, ${componentCls}-nav-operations`]: {
  333. flex: '1 0 auto',
  334. // fix safari scroll problem
  335. flexDirection: 'column'
  336. }
  337. }
  338. },
  339. [`${componentCls}-left`]: {
  340. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  341. [`${componentCls}-ink-bar`]: {
  342. right: {
  343. _skip_check_: true,
  344. value: 0
  345. }
  346. }
  347. },
  348. [`> ${componentCls}-content-holder, > div > ${componentCls}-content-holder`]: {
  349. marginLeft: {
  350. _skip_check_: true,
  351. value: unit(calc(token.lineWidth).mul(-1).equal())
  352. },
  353. borderLeft: {
  354. _skip_check_: true,
  355. value: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorder}`
  356. },
  357. [`> ${componentCls}-content > ${componentCls}-tabpane`]: {
  358. paddingLeft: {
  359. _skip_check_: true,
  360. value: token.paddingLG
  361. }
  362. }
  363. }
  364. },
  365. [`${componentCls}-right`]: {
  366. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  367. order: 1,
  368. [`${componentCls}-ink-bar`]: {
  369. left: {
  370. _skip_check_: true,
  371. value: 0
  372. }
  373. }
  374. },
  375. [`> ${componentCls}-content-holder, > div > ${componentCls}-content-holder`]: {
  376. order: 0,
  377. marginRight: {
  378. _skip_check_: true,
  379. value: calc(token.lineWidth).mul(-1).equal()
  380. },
  381. borderRight: {
  382. _skip_check_: true,
  383. value: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorder}`
  384. },
  385. [`> ${componentCls}-content > ${componentCls}-tabpane`]: {
  386. paddingRight: {
  387. _skip_check_: true,
  388. value: token.paddingLG
  389. }
  390. }
  391. }
  392. }
  393. };
  394. };
  395. const genSizeStyle = token => {
  396. const {
  397. componentCls,
  398. cardPaddingSM,
  399. cardPaddingLG,
  400. cardHeightSM,
  401. cardHeightLG,
  402. horizontalItemPaddingSM,
  403. horizontalItemPaddingLG
  404. } = token;
  405. return {
  406. // >>>>> shared
  407. [componentCls]: {
  408. '&-small': {
  409. [`> ${componentCls}-nav`]: {
  410. [`${componentCls}-tab`]: {
  411. padding: horizontalItemPaddingSM,
  412. fontSize: token.titleFontSizeSM
  413. }
  414. }
  415. },
  416. '&-large': {
  417. [`> ${componentCls}-nav`]: {
  418. [`${componentCls}-tab`]: {
  419. padding: horizontalItemPaddingLG,
  420. fontSize: token.titleFontSizeLG,
  421. lineHeight: token.lineHeightLG
  422. }
  423. }
  424. }
  425. },
  426. // >>>>> card
  427. [`${componentCls}-card`]: {
  428. // Small
  429. [`&${componentCls}-small`]: {
  430. [`> ${componentCls}-nav`]: {
  431. [`${componentCls}-tab`]: {
  432. padding: cardPaddingSM
  433. },
  434. [`${componentCls}-nav-add`]: {
  435. minWidth: cardHeightSM,
  436. minHeight: cardHeightSM
  437. }
  438. },
  439. [`&${componentCls}-bottom`]: {
  440. [`> ${componentCls}-nav ${componentCls}-tab`]: {
  441. borderRadius: `0 0 ${unit(token.borderRadius)} ${unit(token.borderRadius)}`
  442. }
  443. },
  444. [`&${componentCls}-top`]: {
  445. [`> ${componentCls}-nav ${componentCls}-tab`]: {
  446. borderRadius: `${unit(token.borderRadius)} ${unit(token.borderRadius)} 0 0`
  447. }
  448. },
  449. [`&${componentCls}-right`]: {
  450. [`> ${componentCls}-nav ${componentCls}-tab`]: {
  451. borderRadius: {
  452. _skip_check_: true,
  453. value: `0 ${unit(token.borderRadius)} ${unit(token.borderRadius)} 0`
  454. }
  455. }
  456. },
  457. [`&${componentCls}-left`]: {
  458. [`> ${componentCls}-nav ${componentCls}-tab`]: {
  459. borderRadius: {
  460. _skip_check_: true,
  461. value: `${unit(token.borderRadius)} 0 0 ${unit(token.borderRadius)}`
  462. }
  463. }
  464. }
  465. },
  466. // Large
  467. [`&${componentCls}-large`]: {
  468. [`> ${componentCls}-nav`]: {
  469. [`${componentCls}-tab`]: {
  470. padding: cardPaddingLG
  471. },
  472. [`${componentCls}-nav-add`]: {
  473. minWidth: cardHeightLG,
  474. minHeight: cardHeightLG
  475. }
  476. }
  477. }
  478. }
  479. };
  480. };
  481. const genTabStyle = token => {
  482. const {
  483. componentCls,
  484. itemActiveColor,
  485. itemHoverColor,
  486. iconCls,
  487. tabsHorizontalItemMargin,
  488. horizontalItemPadding,
  489. itemSelectedColor,
  490. itemColor
  491. } = token;
  492. const tabCls = `${componentCls}-tab`;
  493. return {
  494. [tabCls]: {
  495. position: 'relative',
  496. WebkitTouchCallout: 'none',
  497. WebkitTapHighlightColor: 'transparent',
  498. display: 'inline-flex',
  499. alignItems: 'center',
  500. padding: horizontalItemPadding,
  501. fontSize: token.titleFontSize,
  502. background: 'transparent',
  503. border: 0,
  504. outline: 'none',
  505. cursor: 'pointer',
  506. color: itemColor,
  507. '&-btn, &-remove': {
  508. '&:focus:not(:focus-visible), &:active': {
  509. color: itemActiveColor
  510. }
  511. },
  512. '&-btn': {
  513. outline: 'none',
  514. transition: `all ${token.motionDurationSlow}`,
  515. [`${tabCls}-icon:not(:last-child)`]: {
  516. marginInlineEnd: token.marginSM
  517. }
  518. },
  519. '&-remove': Object.assign({
  520. flex: 'none',
  521. lineHeight: 1,
  522. marginRight: {
  523. _skip_check_: true,
  524. value: token.calc(token.marginXXS).mul(-1).equal()
  525. },
  526. marginLeft: {
  527. _skip_check_: true,
  528. value: token.marginXS
  529. },
  530. color: token.colorIcon,
  531. fontSize: token.fontSizeSM,
  532. background: 'transparent',
  533. border: 'none',
  534. outline: 'none',
  535. cursor: 'pointer',
  536. transition: `all ${token.motionDurationSlow}`,
  537. '&:hover': {
  538. color: token.colorTextHeading
  539. }
  540. }, genFocusStyle(token)),
  541. '&:hover': {
  542. color: itemHoverColor
  543. },
  544. [`&${tabCls}-active ${tabCls}-btn`]: {
  545. color: itemSelectedColor,
  546. textShadow: token.tabsActiveTextShadow
  547. },
  548. [`&${tabCls}-focus ${tabCls}-btn:focus-visible`]: genFocusOutline(token),
  549. [`&${tabCls}-disabled`]: {
  550. color: token.colorTextDisabled,
  551. cursor: 'not-allowed'
  552. },
  553. [`&${tabCls}-disabled ${tabCls}-btn, &${tabCls}-disabled ${componentCls}-remove`]: {
  554. '&:focus, &:active': {
  555. color: token.colorTextDisabled
  556. }
  557. },
  558. [`& ${tabCls}-remove ${iconCls}`]: {
  559. margin: 0,
  560. verticalAlign: 'middle'
  561. },
  562. [`${iconCls}:not(:last-child)`]: {
  563. marginRight: {
  564. _skip_check_: true,
  565. value: token.marginSM
  566. }
  567. }
  568. },
  569. [`${tabCls} + ${tabCls}`]: {
  570. margin: {
  571. _skip_check_: true,
  572. value: tabsHorizontalItemMargin
  573. }
  574. }
  575. };
  576. };
  577. const genRtlStyle = token => {
  578. const {
  579. componentCls,
  580. tabsHorizontalItemMarginRTL,
  581. iconCls,
  582. cardGutter,
  583. calc
  584. } = token;
  585. const rtlCls = `${componentCls}-rtl`;
  586. return {
  587. [rtlCls]: {
  588. direction: 'rtl',
  589. [`${componentCls}-nav`]: {
  590. [`${componentCls}-tab`]: {
  591. margin: {
  592. _skip_check_: true,
  593. value: tabsHorizontalItemMarginRTL
  594. },
  595. [`${componentCls}-tab:last-of-type`]: {
  596. marginLeft: {
  597. _skip_check_: true,
  598. value: 0
  599. }
  600. },
  601. [iconCls]: {
  602. marginRight: {
  603. _skip_check_: true,
  604. value: 0
  605. },
  606. marginLeft: {
  607. _skip_check_: true,
  608. value: unit(token.marginSM)
  609. }
  610. },
  611. [`${componentCls}-tab-remove`]: {
  612. marginRight: {
  613. _skip_check_: true,
  614. value: unit(token.marginXS)
  615. },
  616. marginLeft: {
  617. _skip_check_: true,
  618. value: unit(calc(token.marginXXS).mul(-1).equal())
  619. },
  620. [iconCls]: {
  621. margin: 0
  622. }
  623. }
  624. }
  625. },
  626. [`&${componentCls}-left`]: {
  627. [`> ${componentCls}-nav`]: {
  628. order: 1
  629. },
  630. [`> ${componentCls}-content-holder`]: {
  631. order: 0
  632. }
  633. },
  634. [`&${componentCls}-right`]: {
  635. [`> ${componentCls}-nav`]: {
  636. order: 0
  637. },
  638. [`> ${componentCls}-content-holder`]: {
  639. order: 1
  640. }
  641. },
  642. // ====================== Card ======================
  643. [`&${componentCls}-card${componentCls}-top, &${componentCls}-card${componentCls}-bottom`]: {
  644. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  645. [`${componentCls}-tab + ${componentCls}-tab`]: {
  646. marginRight: {
  647. _skip_check_: true,
  648. value: cardGutter
  649. },
  650. marginLeft: {
  651. _skip_check_: true,
  652. value: 0
  653. }
  654. }
  655. }
  656. }
  657. },
  658. [`${componentCls}-dropdown-rtl`]: {
  659. direction: 'rtl'
  660. },
  661. [`${componentCls}-menu-item`]: {
  662. [`${componentCls}-dropdown-rtl`]: {
  663. textAlign: {
  664. _skip_check_: true,
  665. value: 'right'
  666. }
  667. }
  668. }
  669. };
  670. };
  671. const genTabsStyle = token => {
  672. const {
  673. componentCls,
  674. tabsCardPadding,
  675. cardHeight,
  676. cardGutter,
  677. itemHoverColor,
  678. itemActiveColor,
  679. colorBorderSecondary
  680. } = token;
  681. return {
  682. [componentCls]: Object.assign(Object.assign(Object.assign(Object.assign({}, resetComponent(token)), {
  683. display: 'flex',
  684. // ========================== Navigation ==========================
  685. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  686. position: 'relative',
  687. display: 'flex',
  688. flex: 'none',
  689. alignItems: 'center',
  690. [`${componentCls}-nav-wrap`]: {
  691. position: 'relative',
  692. display: 'flex',
  693. flex: 'auto',
  694. alignSelf: 'stretch',
  695. overflow: 'hidden',
  696. whiteSpace: 'nowrap',
  697. transform: 'translate(0)',
  698. // Fix chrome render bug
  699. // >>>>> Ping shadow
  700. '&::before, &::after': {
  701. position: 'absolute',
  702. zIndex: 1,
  703. opacity: 0,
  704. transition: `opacity ${token.motionDurationSlow}`,
  705. content: "''",
  706. pointerEvents: 'none'
  707. }
  708. },
  709. [`${componentCls}-nav-list`]: {
  710. position: 'relative',
  711. display: 'flex',
  712. transition: `opacity ${token.motionDurationSlow}`
  713. },
  714. // >>>>>>>> Operations
  715. [`${componentCls}-nav-operations`]: {
  716. display: 'flex',
  717. alignSelf: 'stretch'
  718. },
  719. [`${componentCls}-nav-operations-hidden`]: {
  720. position: 'absolute',
  721. visibility: 'hidden',
  722. pointerEvents: 'none'
  723. },
  724. [`${componentCls}-nav-more`]: {
  725. position: 'relative',
  726. padding: tabsCardPadding,
  727. background: 'transparent',
  728. border: 0,
  729. color: token.colorText,
  730. '&::after': {
  731. position: 'absolute',
  732. right: {
  733. _skip_check_: true,
  734. value: 0
  735. },
  736. bottom: 0,
  737. left: {
  738. _skip_check_: true,
  739. value: 0
  740. },
  741. height: token.calc(token.controlHeightLG).div(8).equal(),
  742. transform: 'translateY(100%)',
  743. content: "''"
  744. }
  745. },
  746. [`${componentCls}-nav-add`]: Object.assign({
  747. minWidth: cardHeight,
  748. minHeight: cardHeight,
  749. marginLeft: {
  750. _skip_check_: true,
  751. value: cardGutter
  752. },
  753. background: 'transparent',
  754. border: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
  755. borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0`,
  756. outline: 'none',
  757. cursor: 'pointer',
  758. color: token.colorText,
  759. transition: `all ${token.motionDurationSlow} ${token.motionEaseInOut}`,
  760. '&:hover': {
  761. color: itemHoverColor
  762. },
  763. '&:active, &:focus:not(:focus-visible)': {
  764. color: itemActiveColor
  765. }
  766. }, genFocusStyle(token, -3))
  767. },
  768. [`${componentCls}-extra-content`]: {
  769. flex: 'none'
  770. },
  771. // ============================ InkBar ============================
  772. [`${componentCls}-ink-bar`]: {
  773. position: 'absolute',
  774. background: token.inkBarColor,
  775. pointerEvents: 'none'
  776. }
  777. }), genTabStyle(token)), {
  778. // =========================== TabPanes ===========================
  779. [`${componentCls}-content`]: {
  780. position: 'relative',
  781. width: '100%'
  782. },
  783. [`${componentCls}-content-holder`]: {
  784. flex: 'auto',
  785. minWidth: 0,
  786. minHeight: 0
  787. },
  788. [`${componentCls}-tabpane`]: Object.assign(Object.assign({}, genFocusStyle(token)), {
  789. '&-hidden': {
  790. display: 'none'
  791. }
  792. })
  793. }),
  794. [`${componentCls}-centered`]: {
  795. [`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
  796. [`${componentCls}-nav-wrap`]: {
  797. [`&:not([class*='${componentCls}-nav-wrap-ping']) > ${componentCls}-nav-list`]: {
  798. margin: 'auto'
  799. }
  800. }
  801. }
  802. }
  803. };
  804. };
  805. export const prepareComponentToken = token => {
  806. const {
  807. cardHeight,
  808. cardHeightSM,
  809. cardHeightLG,
  810. controlHeight,
  811. controlHeightLG
  812. } = token;
  813. const mergedCardHeight = cardHeight || controlHeightLG;
  814. const mergedCardHeightSM = cardHeightSM || controlHeight;
  815. // `controlHeight` missing XL variable, so we directly write it here:
  816. const mergedCardHeightLG = cardHeightLG || controlHeightLG + 8;
  817. return {
  818. zIndexPopup: token.zIndexPopupBase + 50,
  819. cardBg: token.colorFillAlter,
  820. // We can not pass this as valid value,
  821. // Since `cardHeight` will lock nav add button height.
  822. cardHeight: mergedCardHeight,
  823. cardHeightSM: mergedCardHeightSM,
  824. cardHeightLG: mergedCardHeightLG,
  825. // Initialize with empty string, because cardPadding will be calculated with cardHeight by default.
  826. cardPadding: `${(mergedCardHeight - token.fontHeight) / 2 - token.lineWidth}px ${token.padding}px`,
  827. cardPaddingSM: `${(mergedCardHeightSM - token.fontHeight) / 2 - token.lineWidth}px ${token.paddingXS}px`,
  828. cardPaddingLG: `${(mergedCardHeightLG - token.fontHeightLG) / 2 - token.lineWidth}px ${token.padding}px`,
  829. titleFontSize: token.fontSize,
  830. titleFontSizeLG: token.fontSizeLG,
  831. titleFontSizeSM: token.fontSize,
  832. inkBarColor: token.colorPrimary,
  833. horizontalMargin: `0 0 ${token.margin}px 0`,
  834. horizontalItemGutter: 32,
  835. // Fixed Value
  836. // Initialize with empty string, because horizontalItemMargin will be calculated with horizontalItemGutter by default.
  837. horizontalItemMargin: ``,
  838. horizontalItemMarginRTL: ``,
  839. horizontalItemPadding: `${token.paddingSM}px 0`,
  840. horizontalItemPaddingSM: `${token.paddingXS}px 0`,
  841. horizontalItemPaddingLG: `${token.padding}px 0`,
  842. verticalItemPadding: `${token.paddingXS}px ${token.paddingLG}px`,
  843. verticalItemMargin: `${token.margin}px 0 0 0`,
  844. itemColor: token.colorText,
  845. itemSelectedColor: token.colorPrimary,
  846. itemHoverColor: token.colorPrimaryHover,
  847. itemActiveColor: token.colorPrimaryActive,
  848. cardGutter: token.marginXXS / 2
  849. };
  850. };
  851. // ============================== Export ==============================
  852. export default genStyleHooks('Tabs', token => {
  853. const tabsToken = mergeToken(token, {
  854. // `cardPadding` is empty by default, so we could calculate with dynamic `cardHeight`
  855. tabsCardPadding: token.cardPadding,
  856. dropdownEdgeChildVerticalPadding: token.paddingXXS,
  857. tabsActiveTextShadow: '0 0 0.25px currentcolor',
  858. tabsDropdownHeight: 200,
  859. tabsDropdownWidth: 120,
  860. tabsHorizontalItemMargin: `0 0 0 ${unit(token.horizontalItemGutter)}`,
  861. tabsHorizontalItemMarginRTL: `0 0 0 ${unit(token.horizontalItemGutter)}`
  862. });
  863. return [genSizeStyle(tabsToken), genRtlStyle(tabsToken), genPositionStyle(tabsToken), genDropdownStyle(tabsToken), genCardStyle(tabsToken), genTabsStyle(tabsToken), genMotionStyle(tabsToken)];
  864. }, prepareComponentToken);