tooltip.stories.js 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. import React, { useState, useMemo } from 'react';
  2. import Tooltip from '../index';
  3. import './story.scss';
  4. import {
  5. Tag,
  6. Icon,
  7. IconButton,
  8. Switch,
  9. Checkbox,
  10. Radio,
  11. Button,
  12. Select,
  13. InputNumber,
  14. Space,
  15. Popover,
  16. Input,
  17. } from '@douyinfe/semi-ui';
  18. import InTableDemo from './InTable';
  19. import EdgeDemo from './Edge';
  20. import ScrollTooltip from './ScrollDemo';
  21. import DangerousHtml from './DangerousHtml';
  22. import ArrowPointAtCenter from './ArrowPointAtCenter';
  23. import CustomContainer from './CustomContainer';
  24. import ContainerPosition from './ContainerPosition';
  25. import { IconList, IconSidebar, IconEdit } from '@douyinfe/semi-icons';
  26. import TooltipTransition from '../TooltipStyledTransition';
  27. export default {
  28. title: 'Tooltip',
  29. parameters: {
  30. chromatic: { disableSnapshot: true },
  31. },
  32. };
  33. function test(visible) {
  34. console.log('visible Change:' + visible);
  35. }
  36. const ScrollDemo = function ScrollDemo(props = {}) {
  37. const tops = [
  38. ['topLeft', 'TL'],
  39. ['top', 'Top'],
  40. ['topRight', 'TR'],
  41. ];
  42. const lefts = [
  43. ['leftTop', 'LT'],
  44. ['left', 'Left'],
  45. ['leftBottom', 'LB'],
  46. ];
  47. const rights = [
  48. ['rightTop', 'RT'],
  49. ['right', 'Right'],
  50. ['rightBottom', 'RB'],
  51. ];
  52. const bottoms = [
  53. ['bottomLeft', 'BL'],
  54. ['bottom', 'Bottom'],
  55. ['bottomRight', 'BR'],
  56. ];
  57. const { tagStyle, ...restProps } = props;
  58. return (
  59. <div
  60. style={{
  61. paddingLeft: 40,
  62. }}
  63. >
  64. <div
  65. style={{
  66. marginLeft: 40,
  67. whiteSpace: 'nowrap',
  68. }}
  69. >
  70. {tops.map((pos, index) => (
  71. <Tooltip
  72. content={
  73. <article>
  74. <p>hi bytedance</p>
  75. <p>hi bytedance</p>
  76. </article>
  77. }
  78. position={Array.isArray(pos) ? pos[0] : pos}
  79. key={index}
  80. trigger={'click'}
  81. {...restProps}
  82. >
  83. <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  84. </Tooltip>
  85. ))}
  86. </div>
  87. <div
  88. style={{
  89. width: 40,
  90. float: 'left',
  91. }}
  92. >
  93. {lefts.map((pos, index) => (
  94. <Tooltip
  95. content={
  96. <article>
  97. <p>hi bytedance</p>
  98. <p>hi bytedance</p>
  99. </article>
  100. }
  101. position={Array.isArray(pos) ? pos[0] : pos}
  102. key={index}
  103. trigger={'click'}
  104. {...restProps}
  105. >
  106. <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  107. </Tooltip>
  108. ))}
  109. </div>
  110. <div
  111. style={{
  112. width: 40,
  113. marginLeft: 180,
  114. }}
  115. >
  116. {rights.map((pos, index) => (
  117. <Tooltip
  118. content={
  119. <article>
  120. <p>hi bytedance</p>
  121. <p>hi bytedance</p>
  122. </article>
  123. }
  124. position={Array.isArray(pos) ? pos[0] : pos}
  125. key={index}
  126. trigger={'click'}
  127. {...restProps}
  128. >
  129. <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  130. </Tooltip>
  131. ))}
  132. </div>
  133. <div
  134. style={{
  135. marginLeft: 40,
  136. clear: 'both',
  137. whiteSpace: 'nowrap',
  138. }}
  139. >
  140. {bottoms.map((pos, index) => (
  141. <Tooltip
  142. content={
  143. <article>
  144. <p>hi bytedance</p>
  145. <p>hi bytedance</p>
  146. </article>
  147. }
  148. position={Array.isArray(pos) ? pos[0] : pos}
  149. key={index}
  150. trigger={'click'}
  151. {...restProps}
  152. >
  153. <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  154. </Tooltip>
  155. ))}
  156. </div>
  157. </div>
  158. );
  159. };
  160. export const TooltipOnVisibleChange = () => {
  161. const [visible, setVisible] = useState(true);
  162. return (
  163. <div className="demo">
  164. <div>
  165. <label>受控</label>
  166. <Tooltip
  167. content={
  168. <article>
  169. <p>hi bytedance</p>
  170. <p>hi bytedance</p>
  171. </article>
  172. }
  173. position="top"
  174. onVisibleChange={setVisible}
  175. trigger="click"
  176. visible={visible}
  177. >
  178. <Tag>demo</Tag>
  179. </Tooltip>
  180. </div>
  181. <br />
  182. <br />
  183. <div>
  184. <label>非受控</label>
  185. <Tooltip
  186. content={
  187. <article>
  188. <p>hi bytedance</p>
  189. <p>hi bytedance</p>
  190. </article>
  191. }
  192. position="leftTop"
  193. onVisibleChange={test}
  194. trigger="click"
  195. >
  196. <Tag>demo</Tag>
  197. </Tooltip>
  198. </div>
  199. <br />
  200. <br />
  201. {/* <Tooltip
  202. content={
  203. <article>
  204. <p>hi bytedance</p>
  205. <p>hi bytedance</p>
  206. </article>
  207. }
  208. position="rightBottom"
  209. onVisibleChange={test}
  210. trigger="hover"
  211. >
  212. <Tag>hover</Tag>
  213. </Tooltip>
  214. <br />
  215. <br />
  216. <Tooltip
  217. content={
  218. <article>
  219. <p>hi bytedance</p>
  220. <p>hi bytedance</p>
  221. </article>
  222. }
  223. mouseLeaveDelay={100}
  224. position="rightBottom"
  225. onVisibleChange={test}
  226. trigger="hover"
  227. >
  228. <Tag>hover with leave delay time</Tag>
  229. </Tooltip>
  230. <br />
  231. <br />
  232. <Tooltip
  233. content={
  234. <article>
  235. <p>hi bytedance</p>
  236. <p>hi bytedance</p>
  237. </article>
  238. }
  239. position="rightBottom"
  240. onVisibleChange={test}
  241. trigger="click"
  242. >
  243. <Tag>click</Tag>
  244. </Tooltip> */}
  245. </div>
  246. );
  247. };
  248. TooltipOnVisibleChange.story = {
  249. name: 'tooltip onVisibleChange',
  250. };
  251. export const GetPopupContainerDemo = () => (
  252. <div className="demo">
  253. <div className="content-layer" />
  254. <Tooltip
  255. content={
  256. <article>
  257. <p>hi bytedance</p> <p>hi bytedance</p>
  258. </article>
  259. }
  260. position="bottom"
  261. visible
  262. trigger="custom"
  263. getPopupContainer={() => document.querySelector('.content-layer')}
  264. >
  265. <Tag>指定弹出层的容器</Tag>
  266. {/* <div className='content'></div> */}
  267. </Tooltip>
  268. <div>
  269. <label>给定容器为window,看是否报错</label>
  270. <Tooltip content={'单选'} position="top" getPopupContainer={() => window}>
  271. <Radio style={{ display: 'inline-flex' }}>单选</Radio>
  272. </Tooltip>
  273. </div>
  274. </div>
  275. );
  276. GetPopupContainerDemo.story = {
  277. name: 'tooltip指定弹出层的容器',
  278. };
  279. export const TooltipAll = () => (
  280. <div className="demo">
  281. <ScrollDemo />
  282. <div
  283. style={{
  284. padding: 120,
  285. }}
  286. >
  287. <ScrollDemo
  288. showArrow
  289. tagStyle={{
  290. height: 80,
  291. }}
  292. />
  293. </div>
  294. </div>
  295. );
  296. TooltipAll.story = {
  297. name: 'tooltip All',
  298. };
  299. export const NoContent = () => (
  300. <div className="demo">
  301. <div
  302. style={{
  303. padding: 120,
  304. }}
  305. >
  306. <ScrollDemo showArrow content={''} />
  307. </div>
  308. <div
  309. style={{
  310. padding: 120,
  311. }}
  312. >
  313. <ScrollDemo
  314. showArrow
  315. tagStyle={{
  316. minHeight: 80,
  317. minWidth: 120,
  318. }}
  319. content={''}
  320. />
  321. </div>
  322. </div>
  323. );
  324. NoContent.story = {
  325. name: 'no content',
  326. };
  327. export const AdjustPosition = () => (
  328. <>
  329. <div className="adjust">
  330. <div className="wrapper">
  331. 第一个滚动区域
  332. <Tooltip
  333. content={
  334. <article>
  335. <p>hi bytedance</p>
  336. <p>hi bytedance</p>
  337. </article>
  338. }
  339. position="rightBottom"
  340. trigger="click"
  341. >
  342. {/* <Tag className='topLeft'>topleft</Tag> */}
  343. <div>test</div>
  344. </Tooltip>
  345. <Tooltip
  346. content={
  347. <article>
  348. <p>hi bytedance</p>
  349. <p>hi bytedance</p>
  350. </article>
  351. }
  352. position="topRight"
  353. trigger="click"
  354. >
  355. <Tag className="topRight">topRight</Tag>
  356. </Tooltip>
  357. <Tooltip
  358. content={
  359. <article>
  360. <p>hi bytedance</p>
  361. <p>hi bytedance</p>
  362. </article>
  363. }
  364. position="bottomLeft"
  365. trigger="click"
  366. >
  367. <Tag className="bottomLeft">bottomLeft</Tag>
  368. </Tooltip>
  369. <Tooltip
  370. content={
  371. <article>
  372. <p>hi bytedance</p>
  373. <p>hi bytedance</p>
  374. </article>
  375. }
  376. position="bottomRight"
  377. trigger="click"
  378. >
  379. <Tag className="bottomRight">bottomRight</Tag>
  380. </Tooltip>
  381. </div>
  382. </div>
  383. <div className="adjust2">
  384. <div className="wrapper2">第二个滚动区域</div>
  385. </div>
  386. </>
  387. );
  388. AdjustPosition.story = {
  389. name: '自适应',
  390. };
  391. export const AdjustPosIfNeed = () => {
  392. const tops = [
  393. ['topLeft', 'TL'],
  394. ['top', 'Top'],
  395. ['topRight', 'TR'],
  396. ];
  397. const lefts = [
  398. ['leftTop', 'LT'],
  399. ['left', 'Left'],
  400. ['leftBottom', 'LB'],
  401. ];
  402. const rights = [
  403. ['rightTop', 'RT'],
  404. ['right', 'Right'],
  405. ['rightBottom', 'RB'],
  406. ];
  407. const bottoms = [
  408. ['bottomLeft', 'BL'],
  409. ['bottom', 'Bottom'],
  410. ['bottomRight', 'BR'],
  411. ];
  412. return (
  413. <div style={{ paddingLeft: 40 }}>
  414. <div style={{ marginLeft: 40, whiteSpace: 'nowrap' }}>
  415. {tops.map((pos, index) => (
  416. <Tooltip
  417. showArrow
  418. arrowPointAtCenter
  419. content={
  420. <article>
  421. Hi ByteDancer, this is a tooltip.
  422. <br /> We have 2 lines.
  423. </article>
  424. }
  425. position={Array.isArray(pos) ? pos[0] : pos}
  426. key={index}
  427. >
  428. <Tag
  429. style={{ marginRight: '8px' }}
  430. data-cy={Array.isArray(pos) ? pos[0] : pos}
  431. >
  432. {Array.isArray(pos) ? pos[1] : pos}
  433. </Tag>
  434. </Tooltip>
  435. ))}
  436. </div>
  437. <div style={{ width: 40, float: 'left' }}>
  438. {lefts.map((pos, index) => (
  439. <Tooltip
  440. showArrow
  441. arrowPointAtCenter
  442. content={
  443. <article>
  444. Hi ByteDancer, this is a tooltip.
  445. <br /> We have 2 lines.
  446. </article>
  447. }
  448. position={Array.isArray(pos) ? pos[0] : pos}
  449. key={index}
  450. >
  451. <Tag data-cy={Array.isArray(pos) ? pos[0] : pos} style={{ marginBottom: '8px' }}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  452. </Tooltip>
  453. ))}
  454. </div>
  455. <div style={{ width: 40, marginLeft: 180 }}>
  456. {rights.map((pos, index) => (
  457. <Tooltip
  458. showArrow
  459. arrowPointAtCenter
  460. content={
  461. <article>
  462. Hi ByteDancer, this is a tooltip.
  463. <br /> We have 2 lines.
  464. </article>
  465. }
  466. position={Array.isArray(pos) ? pos[0] : pos}
  467. key={index}
  468. >
  469. <Tag data-cy={Array.isArray(pos) ? pos[0] : pos} style={{ marginBottom: '8px' }}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  470. </Tooltip>
  471. ))}
  472. </div>
  473. <div style={{ marginLeft: 40, clear: 'both', whiteSpace: 'nowrap' }}>
  474. {bottoms.map((pos, index) => (
  475. <Tooltip
  476. showArrow
  477. arrowPointAtCenter
  478. content={
  479. <article>
  480. Hi ByteDancer, this is a tooltip.
  481. <br /> We have 2 lines.
  482. </article>
  483. }
  484. position={Array.isArray(pos) ? pos[0] : pos}
  485. key={index}
  486. >
  487. <Tag data-cy={Array.isArray(pos) ? pos[0] : pos} position={Array.isArray(pos) ? pos[0] : pos} style={{ marginRight: '8px' }}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  488. </Tooltip>
  489. ))}
  490. </div>
  491. </div>
  492. );
  493. }
  494. AdjustPosIfNeed.story = {
  495. name: '自适应位置',
  496. };
  497. export const CompositeComponent = () => (
  498. <div
  499. style={{
  500. padding: 50,
  501. }}
  502. >
  503. <Tooltip
  504. content={
  505. <article>
  506. <p>hi bytedance</p> <p>hi bytedance</p>
  507. </article>
  508. }
  509. position="top"
  510. >
  511. <IconList />
  512. </Tooltip>
  513. <Tooltip content={'收起'} position="top">
  514. <IconButton icon={<IconSidebar />} />
  515. </Tooltip>
  516. <Tooltip content={'开关'} position="top">
  517. <Switch />
  518. </Tooltip>
  519. <Tooltip content={'选择框'} position="top">
  520. <Checkbox
  521. style={{
  522. display: 'inline-flex',
  523. }}
  524. >
  525. 选择框
  526. </Checkbox>
  527. </Tooltip>
  528. <Tooltip content={'单选'} position="top">
  529. <Radio
  530. style={{
  531. display: 'inline-flex',
  532. }}
  533. >
  534. 单选
  535. </Radio>
  536. </Tooltip>
  537. </div>
  538. );
  539. CompositeComponent.story = {
  540. name: '复合组件',
  541. };
  542. export const WrapDisabledElems = () => (
  543. <div
  544. style={{
  545. padding: 50,
  546. }}
  547. >
  548. <Tooltip content="disabled">
  549. <IconButton disabled icon={<IconEdit />} />
  550. </Tooltip>
  551. <Tooltip content="disabled">
  552. <IconButton disabled icon={<IconEdit />} block />
  553. </Tooltip>
  554. <Tooltip content="disabled">
  555. <Button disabled block>
  556. 编辑
  557. </Button>
  558. </Tooltip>
  559. <Tooltip content="disabled">
  560. <Button
  561. disabled
  562. style={{
  563. display: 'block',
  564. }}
  565. >
  566. 编辑
  567. </Button>
  568. </Tooltip>
  569. </div>
  570. );
  571. WrapDisabledElems.story = {
  572. name: 'wrap disabled elems',
  573. };
  574. export const InTable = () => (
  575. <div
  576. style={{
  577. marginTop: 50,
  578. }}
  579. >
  580. <InTableDemo />
  581. </div>
  582. );
  583. InTable.story = {
  584. name: 'in table',
  585. };
  586. export const _EdgeDemo = () => <EdgeDemo />;
  587. _EdgeDemo.story = {
  588. name: 'edge demo',
  589. };
  590. export const ScrollTooltipDemo = () => <ScrollTooltip />;
  591. ScrollTooltipDemo.story = {
  592. name: 'scroll demo and set popup container',
  593. };
  594. export const DangerousHtmlDemo = () => <DangerousHtml />;
  595. DangerousHtmlDemo.story = {
  596. name: 'in dangerous html',
  597. };
  598. export const ArrowPointAtCenterDemo = () => <ArrowPointAtCenter />;
  599. ArrowPointAtCenterDemo.story = {
  600. name: 'arrow point at center',
  601. };
  602. export const CustomContainerDemo = () => <CustomContainer />;
  603. CustomContainerDemo.story = {
  604. name: 'custom container',
  605. };
  606. export const ContainerPositionDemo = () => <ContainerPosition />;
  607. ContainerPositionDemo.story = {
  608. name: 'container observer',
  609. };
  610. export const QuickMoveMouse = () => {
  611. /**
  612. * mouseEnterDelay, mouseLeaveDelay 默认都为 50
  613. * mouseEnterDelay, mouseLeaveDelay 都为 0,快速滑动可能出现两个 tooltip 出现
  614. */
  615. const Demo = () => {
  616. const props = {
  617. mouseEnterDelay: 50,
  618. mouseLeaveDelay: 0,
  619. };
  620. return (
  621. <div className="demo">
  622. <div>
  623. <Tooltip content={'1'} {...props}>
  624. aaaaaaaaaaa
  625. </Tooltip>
  626. </div>
  627. <div>
  628. <Tooltip content={'2'} {...props}>
  629. bbbbbbbbbbb
  630. </Tooltip>
  631. </div>
  632. <div>
  633. <Tooltip content={'3'} {...props}>
  634. ccccccccccc
  635. </Tooltip>
  636. </div>
  637. <div>
  638. <Tooltip content={'4'} {...props}>
  639. aaaaaaaaaaa
  640. </Tooltip>
  641. </div>
  642. <div>
  643. <Tooltip content={'5'} {...props}>
  644. bbbbbbbbbbb
  645. </Tooltip>
  646. </div>
  647. <div>
  648. <Tooltip content={'6'} {...props}>
  649. ccccccccccc
  650. </Tooltip>
  651. </div>
  652. <div>
  653. <Tooltip content={'7'} {...props}>
  654. aaaaaaaaaaa
  655. </Tooltip>
  656. </div>
  657. <div>
  658. <Tooltip content={'8'} {...props}>
  659. bbbbbbbbbbb
  660. </Tooltip>
  661. </div>
  662. <div>
  663. <Tooltip content={'9'} {...props}>
  664. ccccccccccc
  665. </Tooltip>
  666. </div>
  667. </div>
  668. );
  669. };
  670. return <Demo />;
  671. };
  672. QuickMoveMouse.story = {
  673. name: '快速移动鼠标可见性',
  674. };
  675. export const MotionFalseFix1402 = () => {
  676. function Demo() {
  677. const Test = React.forwardRef((props, ref) => (
  678. <span {...props} ref={ref}>
  679. Test
  680. </span>
  681. ));
  682. return (
  683. <div>
  684. <Tooltip content={'hi bytedance'} motion={false}>
  685. <Test />
  686. </Tooltip>
  687. <br />
  688. <br />
  689. <Tooltip content={'hi bytedance'}>
  690. <Test />
  691. </Tooltip>
  692. </div>
  693. );
  694. }
  695. return <Demo />;
  696. };
  697. MotionFalseFix1402.story = {
  698. name: 'motion=false fix #1402',
  699. };
  700. export const DisabledWrapperCls = () => (
  701. <>
  702. <Tooltip wrapperClassName="test" content={'hi bytedance'}>
  703. <Button>按钮</Button>
  704. </Tooltip>
  705. <br />
  706. <br />
  707. <Tooltip wrapperClassName="test" content={'hi bytedance'}>
  708. <Button disabled>禁用的单个按钮</Button>
  709. </Tooltip>
  710. <br />
  711. <br />
  712. <Tooltip wrapperClassName="test" content={'hi bytedance'}>
  713. <Button>正常的多个按钮</Button>
  714. <Button>正常的多个按钮</Button>
  715. </Tooltip>
  716. <br />
  717. <br />
  718. <Tooltip wrapperClassName="test" content={'hi bytedance'}>
  719. <Select disabled placeholder="请选择业务线" style={{ width: 120 }}>
  720. <Select.Option value="abc">抖音</Select.Option>
  721. <Select.Option value="hotsoon">火山</Select.Option>
  722. <Select.Option value="jianying" disabled>
  723. 剪映
  724. </Select.Option>
  725. <Select.Option value="xigua">西瓜视频</Select.Option>
  726. </Select>
  727. </Tooltip>
  728. <br />
  729. <br />
  730. </>
  731. );
  732. DisabledWrapperCls.story = {
  733. name: 'disabledWrapperCls',
  734. };
  735. export const ShowArrow = () => {
  736. function Demo() {
  737. const Test = React.forwardRef((props, ref) => (
  738. <Tag {...props} ref={ref}>
  739. Test
  740. </Tag>
  741. ));
  742. return (
  743. <div>
  744. <h4>should show content and arrow when click</h4>
  745. <Tooltip showArrow trigger="click" content={'hi bytedance'}>
  746. <Test />
  747. </Tooltip>
  748. </div>
  749. );
  750. }
  751. return <Demo />;
  752. };
  753. ShowArrow.story = {
  754. name: 'showArrow',
  755. };
  756. export const OnClickOutSideDemo = () => {
  757. let [v, setV] = useState(false);
  758. let clickOutSide = () => {
  759. console.log('clickOutSide');
  760. setV(false);
  761. };
  762. return (
  763. <>
  764. <Tooltip onClickOutSide={() => clickOutSide()} content={'hi bytedance'} visible={v} trigger="custom">
  765. <Button onClick={() => setV(true)}>按钮</Button>
  766. </Tooltip>
  767. <br />
  768. <br />
  769. <Tooltip onClickOutSide={() => console.log('clickOutSide')} content={'hi bytedance'} trigger="click">
  770. <Button>单个按钮</Button>
  771. </Tooltip>
  772. </>
  773. );
  774. };
  775. OnClickOutSideDemo.story = {
  776. name: 'OnClickOutSide',
  777. };
  778. export const AutoAdjustWithSpacing = () => {
  779. const [height, setHeight] = useState(84);
  780. const [key, setKey] = useState(1);
  781. const initSpacing = 8;
  782. const [spacing, setSpacing] = useState(initSpacing);
  783. const change = (height, hasSpace) => {
  784. setHeight(height);
  785. hasSpace ? setSpacing(initSpacing) : setSpacing(0);
  786. setKey(Math.random());
  787. };
  788. return (
  789. <div className="demo1">
  790. <div>
  791. <Tooltip
  792. motion={false}
  793. rePosKey={key}
  794. // spacing={spacing}
  795. content={
  796. <article style={{ boxSizing: 'border-box', height: height }}>
  797. <p>hi bytedance, + padding 20</p>
  798. <p>hi bytedance</p>
  799. </article>
  800. }
  801. position="top"
  802. trigger="custom"
  803. visible={true}
  804. >
  805. <Tag>demo</Tag>
  806. </Tooltip>
  807. </div>
  808. <div style={{ marginTop: 200 }}>
  809. <Switch
  810. onChange={hasSpace => change(height, hasSpace)}
  811. checked={spacing === initSpacing ? true : false}
  812. ></Switch>
  813. <InputNumber onChange={height => change(Number(height))} value={height} style={{ width: 200 }} />
  814. </div>
  815. </div>
  816. );
  817. };
  818. AutoAdjustWithSpacing.story = {
  819. name: 'AutoAdjustWithSpacing',
  820. };
  821. /**
  822. * Chromatic UI test
  823. */
  824. export const leftTopOverDemo = () => {
  825. const [visible, setVisible] = useState(true);
  826. const content = <div style={{ height: 200, width: 200 }}>Semi Design</div>;
  827. const commonProps = {
  828. content,
  829. trigger: 'click',
  830. showArrow: false,
  831. visible:true,
  832. trigger: 'custom',
  833. motion: false,
  834. };
  835. const buttonStyle = {
  836. width: 200,
  837. };
  838. return (
  839. <div data-cy="wrapper">
  840. <Button onClick={() => setVisible(!visible)} data-cy="toggleVisible">toggle visible</Button>
  841. <div style={{ paddingTop: 110 }}>
  842. <Space spacing={80}>
  843. <Tooltip {...commonProps} position="leftBottomOver" trigger="click">
  844. <Button data-cy="leftBottomOver" style={buttonStyle}>
  845. leftBottomOver
  846. </Button>
  847. </Tooltip>
  848. <Tooltip {...commonProps} position="rightBottomOver" trigger="click">
  849. <Button data-cy="rightBottomOver" style={buttonStyle}>
  850. rightBottomOver
  851. </Button>
  852. </Tooltip>
  853. </Space>
  854. </div>
  855. <Space spacing={80}>
  856. <Tooltip {...commonProps} position="leftTopOver" trigger="click">
  857. <Button data-cy="leftTopOver" style={buttonStyle}>
  858. leftTopOver
  859. </Button>
  860. </Tooltip>
  861. <Tooltip {...commonProps} position="rightTopOver" trigger="click">
  862. <Button data-cy="rightTopOver" style={buttonStyle}>
  863. rightTopOver
  864. </Button>
  865. </Tooltip>
  866. </Space>
  867. </div>
  868. );
  869. };
  870. leftTopOverDemo.storyName = `leftTopOver visible`;
  871. leftTopOverDemo.parameters = {
  872. chromatic: {
  873. disableSnapshot: false,
  874. delay: 3000,
  875. viewports: [1200],
  876. },
  877. };
  878. /**
  879. * Cypress test
  880. */
  881. export const leftTopOverAutoAdjustOverflow = () => {
  882. const content = <div style={{ height: 200, width: 200 }}>Semi Design</div>;
  883. const commonProps = {
  884. content,
  885. trigger: 'click',
  886. showArrow: false,
  887. };
  888. return (
  889. <div
  890. data-cy="wrapper"
  891. style={{ width: '200vw', height: '200vw', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
  892. >
  893. <div>
  894. <Tooltip {...commonProps} position="leftTopOver">
  895. <Button data-cy="leftTopOver" style={{ width: 200 }}>
  896. leftTopOver
  897. </Button>
  898. </Tooltip>
  899. </div>
  900. </div>
  901. );
  902. };
  903. leftTopOverAutoAdjustOverflow.storyName = `leftTopOver autoAdjustOverflow`;
  904. export const autoFocusContentDemo = () => {
  905. const [controlMotionVisible, setControlMotionVisible] = React.useState(false);
  906. const [controlNoMotionVisible, setControlNoMotionVisible] = React.useState(false);
  907. const onMotionVisibleChange = React.useCallback(() => {
  908. setControlMotionVisible(!controlMotionVisible);
  909. }, [setControlMotionVisible, controlMotionVisible]);
  910. const onNoMotionVisibleChange = React.useCallback(() => {
  911. setControlNoMotionVisible(!controlNoMotionVisible);
  912. }, [setControlNoMotionVisible, controlNoMotionVisible]);
  913. return (
  914. <div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
  915. <div style={{ display: 'flex', gap: 18, flex: 1, alignItems: 'center' }}>
  916. <span>Hover触发</span>
  917. <Popover position="bottomLeft" content={<Input autofocus data-cy="hoverInput"/>}>
  918. <Button data-cy="hover">motion</Button>
  919. </Popover>
  920. <Popover motion={false} position="bottomLeft" content={<Input autofocus data-cy="hoverNoMotionInput"/>}>
  921. <Button data-cy="hoverNoMotion">no motion</Button>
  922. </Popover>
  923. </div>
  924. <div style={{ display: 'flex', gap: 18, flex: 1, alignItems: 'center' }}>
  925. <span>Click触发</span>
  926. <Popover position="bottomLeft" content={<Input autofocus data-cy="clickInput"/>} trigger="click">
  927. <Button data-cy="click">motion</Button>
  928. </Popover>
  929. <Popover motion={false} position="bottomLeft" content={<Input autofocus data-cy="clickNoMotionInput"/>} trigger="click">
  930. <Button data-cy="clickNoMotion">no motion</Button>
  931. </Popover>
  932. </div>
  933. <div style={{ display: 'flex', gap: 18, flex: 1, alignItems: 'center' }}>
  934. <span>受控</span>
  935. <Button onClick={onMotionVisibleChange} data-cy="controlled">motion状态切换</Button>
  936. <Popover visible={controlMotionVisible} trigger="custom" position="bottomLeft" content={<Input autofocus data-cy="controlledInput"/>}>
  937. <Button disabled data-cy="controlledDisableBtn">motion</Button>
  938. </Popover>
  939. <Button onClick={onNoMotionVisibleChange } data-cy="controlledNoMotion">no motion状态切换</Button>
  940. <Popover
  941. visible={controlNoMotionVisible}
  942. trigger="custom"
  943. motion={false}
  944. position="bottomLeft"
  945. content={<Input autofocus data-cy="controlledNoMotionInput"/>}
  946. >
  947. <Button disabled data-cy="controlledNoMotionDisableBtn">no motion</Button>
  948. </Popover>
  949. </div>
  950. </div>
  951. );
  952. };
  953. export const FlashWithReact18 = () => {
  954. const [visible, setV] = useState(false);
  955. const change = () => {
  956. setV(false);
  957. }
  958. return (<>
  959. <Tooltip content='test work with react 18' position='bottom' trigger='custom' visible={visible}>
  960. <Button style={{ marginLeft: 10 }} onClick={() => setV(true)}>show, semi with react 18 motion=true, abnormal</Button>
  961. </Tooltip>
  962. <Button style={{ marginLeft: 10 }} onClick={() => change()}>hide</Button>
  963. </>);
  964. }
  965. export const Transition = () => {
  966. const [transitionState, setT] = useState('');
  967. const [insert, setInsert] = useState(false);
  968. const handleLeave = () => {
  969. console.log('set insert false')
  970. setInsert(false);
  971. }
  972. const CommonDOM = () => {
  973. const enterCls = `semi-tooltip-bounceIn`;
  974. const leaveCls = `semi-tooltip-zoomOut`;
  975. const animateStyle = {
  976. animationDirection: 'normal',
  977. animationName: transitionState === 'enter' ? enterCls : leaveCls,
  978. animationDuration: '1000ms',
  979. }
  980. const handleEnd = () => {
  981. if (transitionState === 'enter') {
  982. console.log('animation end of show');
  983. } else if (transitionState === 'leave') {
  984. console.log('animation end of hide');
  985. handleLeave();
  986. }
  987. }
  988. return <div style={{ ...animateStyle }} onAnimationEnd={handleEnd}>test</div>
  989. };
  990. const toggleShow = (insert) => {
  991. if (!transitionState) {
  992. setT('enter');
  993. setInsert(insert);
  994. } else if (transitionState === 'enter') {
  995. setT('leave');
  996. } else if (transitionState === 'leave') {
  997. setT('enter');
  998. setInsert(insert);
  999. }
  1000. };
  1001. return (
  1002. <>
  1003. <div style={{ width: 200, height: 90, border: '1px solid var(--semi-color-text-1)' }}>
  1004. {
  1005. insert ? (
  1006. <CommonDOM></CommonDOM>
  1007. ): null
  1008. }
  1009. </div>
  1010. <Button onClick={() => toggleShow(true)}>show</Button>
  1011. <Button onClick={() => toggleShow(false)}>hide</Button>
  1012. </>
  1013. )
  1014. }
  1015. export const TransitionDemo = () => {
  1016. const [key, setKey] = useState(1);
  1017. return (
  1018. <>
  1019. <Transition key={key} />
  1020. <Button onClick={() => setKey(Math.random())}>reset Demo</Button>
  1021. </>
  1022. )
  1023. }