tooltip.stories.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. import React, { useState, useMemo } from 'react';
  2. import Tooltip from '../index';
  3. import './story.scss';
  4. import { Tag, Icon, IconButton, Switch, Checkbox, Radio, Button, Select, InputNumber } from '@douyinfe/semi-ui';
  5. import InTableDemo from './InTable';
  6. import EdgeDemo from './Edge';
  7. import ScrollTooltip from './ScrollDemo';
  8. import DangerousHtml from './DangerousHtml';
  9. import ArrowPointAtCenter from './ArrowPointAtCenter';
  10. import CustomContainer from './CustomContainer';
  11. import ContainerPosition from './ContainerPosition';
  12. import { IconList, IconSidebar, IconEdit } from '@douyinfe/semi-icons';
  13. export default {
  14. title: 'Tooltip',
  15. parameters: {
  16. chromatic: { disableSnapshot: true },
  17. },
  18. }
  19. function test(visible) {
  20. console.log('visible Change:' + visible);
  21. }
  22. const ScrollDemo = function ScrollDemo(props = {}) {
  23. const tops = [
  24. ['topLeft', 'TL'],
  25. ['top', 'Top'],
  26. ['topRight', 'TR'],
  27. ];
  28. const lefts = [
  29. ['leftTop', 'LT'],
  30. ['left', 'Left'],
  31. ['leftBottom', 'LB'],
  32. ];
  33. const rights = [
  34. ['rightTop', 'RT'],
  35. ['right', 'Right'],
  36. ['rightBottom', 'RB'],
  37. ];
  38. const bottoms = [
  39. ['bottomLeft', 'BL'],
  40. ['bottom', 'Bottom'],
  41. ['bottomRight', 'BR'],
  42. ];
  43. const { tagStyle, ...restProps } = props;
  44. return (
  45. <div
  46. style={{
  47. paddingLeft: 40,
  48. }}
  49. >
  50. <div
  51. style={{
  52. marginLeft: 40,
  53. whiteSpace: 'nowrap',
  54. }}
  55. >
  56. {tops.map((pos, index) => (
  57. <Tooltip
  58. content={
  59. <article>
  60. <p>hi bytedance</p>
  61. <p>hi bytedance</p>
  62. </article>
  63. }
  64. position={Array.isArray(pos) ? pos[0] : pos}
  65. key={index}
  66. trigger={'click'}
  67. {...restProps}
  68. >
  69. <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  70. </Tooltip>
  71. ))}
  72. </div>
  73. <div
  74. style={{
  75. width: 40,
  76. float: 'left',
  77. }}
  78. >
  79. {lefts.map((pos, index) => (
  80. <Tooltip
  81. content={
  82. <article>
  83. <p>hi bytedance</p>
  84. <p>hi bytedance</p>
  85. </article>
  86. }
  87. position={Array.isArray(pos) ? pos[0] : pos}
  88. key={index}
  89. trigger={'click'}
  90. {...restProps}
  91. >
  92. <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  93. </Tooltip>
  94. ))}
  95. </div>
  96. <div
  97. style={{
  98. width: 40,
  99. marginLeft: 180,
  100. }}
  101. >
  102. {rights.map((pos, index) => (
  103. <Tooltip
  104. content={
  105. <article>
  106. <p>hi bytedance</p>
  107. <p>hi bytedance</p>
  108. </article>
  109. }
  110. position={Array.isArray(pos) ? pos[0] : pos}
  111. key={index}
  112. trigger={'click'}
  113. {...restProps}
  114. >
  115. <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  116. </Tooltip>
  117. ))}
  118. </div>
  119. <div
  120. style={{
  121. marginLeft: 40,
  122. clear: 'both',
  123. whiteSpace: 'nowrap',
  124. }}
  125. >
  126. {bottoms.map((pos, index) => (
  127. <Tooltip
  128. content={
  129. <article>
  130. <p>hi bytedance</p>
  131. <p>hi bytedance</p>
  132. </article>
  133. }
  134. position={Array.isArray(pos) ? pos[0] : pos}
  135. key={index}
  136. trigger={'click'}
  137. {...restProps}
  138. >
  139. <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
  140. </Tooltip>
  141. ))}
  142. </div>
  143. </div>
  144. );
  145. };
  146. export const TooltipOnVisibleChange = () => {
  147. const [visible, setVisible] = useState();
  148. return (
  149. <div className="demo">
  150. <div>
  151. <label>非受控</label>
  152. <Tooltip
  153. content={
  154. <article>
  155. <p>hi bytedance</p>
  156. <p>hi bytedance</p>
  157. </article>
  158. }
  159. position="rightBottom"
  160. onVisibleChange={test}
  161. trigger="click"
  162. >
  163. <Tag>demo</Tag>
  164. </Tooltip>
  165. </div>
  166. <div>
  167. <label>受控</label>
  168. <Tooltip
  169. content={
  170. <article>
  171. <p>hi bytedance</p>
  172. <p>hi bytedance</p>
  173. </article>
  174. }
  175. position="rightBottom"
  176. onVisibleChange={setVisible}
  177. trigger="click"
  178. visible={visible}
  179. >
  180. <Tag>demo</Tag>
  181. </Tooltip>
  182. </div>
  183. <br />
  184. <br />
  185. {/* <Tooltip
  186. content={
  187. <article>
  188. <p>hi bytedance</p>
  189. <p>hi bytedance</p>
  190. </article>
  191. }
  192. position="rightBottom"
  193. onVisibleChange={test}
  194. trigger="hover"
  195. >
  196. <Tag>hover</Tag>
  197. </Tooltip>
  198. <br />
  199. <br />
  200. <Tooltip
  201. content={
  202. <article>
  203. <p>hi bytedance</p>
  204. <p>hi bytedance</p>
  205. </article>
  206. }
  207. mouseLeaveDelay={100}
  208. position="rightBottom"
  209. onVisibleChange={test}
  210. trigger="hover"
  211. >
  212. <Tag>hover with leave delay time</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. position="rightBottom"
  224. onVisibleChange={test}
  225. trigger="click"
  226. >
  227. <Tag>click</Tag>
  228. </Tooltip> */}
  229. </div>
  230. );
  231. };
  232. TooltipOnVisibleChange.story = {
  233. name: 'tooltip onVisibleChange',
  234. };
  235. export const GetPopupContainerDemo = () => (
  236. <div className="demo">
  237. <div className="content-layer" />
  238. <Tooltip
  239. content={
  240. <article>
  241. <p>hi bytedance</p> <p>hi bytedance</p>
  242. </article>
  243. }
  244. position="bottom"
  245. visible
  246. trigger="custom"
  247. getPopupContainer={() => document.querySelector('.content-layer')}
  248. >
  249. <Tag>指定弹出层的容器</Tag>
  250. {/* <div className='content'></div> */}
  251. </Tooltip>
  252. <div>
  253. <label>给定容器为window,看是否报错</label>
  254. <Tooltip content={'单选'} position="top" getPopupContainer={() => window}>
  255. <Radio style={{ display: 'inline-flex' }}>单选</Radio>
  256. </Tooltip>
  257. </div>
  258. </div>
  259. );
  260. GetPopupContainerDemo.story = {
  261. name: 'tooltip指定弹出层的容器',
  262. };
  263. export const TooltipAll = () => (
  264. <div className="demo">
  265. <ScrollDemo />
  266. <div
  267. style={{
  268. padding: 120,
  269. }}
  270. >
  271. <ScrollDemo
  272. showArrow
  273. tagStyle={{
  274. height: 80,
  275. }}
  276. />
  277. </div>
  278. </div>
  279. );
  280. TooltipAll.story = {
  281. name: 'tooltip All',
  282. };
  283. export const NoContent = () => (
  284. <div className="demo">
  285. <div
  286. style={{
  287. padding: 120,
  288. }}
  289. >
  290. <ScrollDemo showArrow content={''} />
  291. </div>
  292. <div
  293. style={{
  294. padding: 120,
  295. }}
  296. >
  297. <ScrollDemo
  298. showArrow
  299. tagStyle={{
  300. minHeight: 80,
  301. minWidth: 120,
  302. }}
  303. content={''}
  304. />
  305. </div>
  306. </div>
  307. );
  308. NoContent.story = {
  309. name: 'no content',
  310. };
  311. export const AdjustPosition = () => (
  312. <>
  313. <div className="adjust">
  314. <div className="wrapper">
  315. 第一个滚动区域
  316. <Tooltip
  317. content={
  318. <article>
  319. <p>hi bytedance</p>
  320. <p>hi bytedance</p>
  321. </article>
  322. }
  323. position="rightBottom"
  324. trigger="click"
  325. >
  326. {/* <Tag className='topLeft'>topleft</Tag> */}
  327. <div>test</div>
  328. </Tooltip>
  329. <Tooltip
  330. content={
  331. <article>
  332. <p>hi bytedance</p>
  333. <p>hi bytedance</p>
  334. </article>
  335. }
  336. position="topRight"
  337. trigger="click"
  338. >
  339. <Tag className="topRight">topRight</Tag>
  340. </Tooltip>
  341. <Tooltip
  342. content={
  343. <article>
  344. <p>hi bytedance</p>
  345. <p>hi bytedance</p>
  346. </article>
  347. }
  348. position="bottomLeft"
  349. trigger="click"
  350. >
  351. <Tag className="bottomLeft">bottomLeft</Tag>
  352. </Tooltip>
  353. <Tooltip
  354. content={
  355. <article>
  356. <p>hi bytedance</p>
  357. <p>hi bytedance</p>
  358. </article>
  359. }
  360. position="bottomRight"
  361. trigger="click"
  362. >
  363. <Tag className="bottomRight">bottomRight</Tag>
  364. </Tooltip>
  365. </div>
  366. </div>
  367. <div className="adjust2">
  368. <div className="wrapper2">第二个滚动区域</div>
  369. </div>
  370. </>
  371. );
  372. AdjustPosition.story = {
  373. name: '自适应'
  374. }
  375. export const CompositeComponent = () => (
  376. <div
  377. style={{
  378. padding: 50,
  379. }}
  380. >
  381. <Tooltip
  382. content={
  383. <article>
  384. <p>hi bytedance</p> <p>hi bytedance</p>
  385. </article>
  386. }
  387. position="top"
  388. >
  389. <IconList />
  390. </Tooltip>
  391. <Tooltip content={'收起'} position="top">
  392. <IconButton icon={<IconSidebar />} />
  393. </Tooltip>
  394. <Tooltip content={'开关'} position="top">
  395. <Switch />
  396. </Tooltip>
  397. <Tooltip content={'选择框'} position="top">
  398. <Checkbox
  399. style={{
  400. display: 'inline-flex',
  401. }}
  402. >
  403. 选择框
  404. </Checkbox>
  405. </Tooltip>
  406. <Tooltip content={'单选'} position="top">
  407. <Radio
  408. style={{
  409. display: 'inline-flex',
  410. }}
  411. >
  412. 单选
  413. </Radio>
  414. </Tooltip>
  415. </div>
  416. );
  417. CompositeComponent.story = {
  418. name: '复合组件'
  419. }
  420. export const WrapDisabledElems = () => (
  421. <div
  422. style={{
  423. padding: 50,
  424. }}
  425. >
  426. <Tooltip content="disabled">
  427. <IconButton disabled icon={<IconEdit />} />
  428. </Tooltip>
  429. <Tooltip content="disabled">
  430. <IconButton disabled icon={<IconEdit />} block />
  431. </Tooltip>
  432. <Tooltip content="disabled">
  433. <Button disabled block>
  434. 编辑
  435. </Button>
  436. </Tooltip>
  437. <Tooltip content="disabled">
  438. <Button
  439. disabled
  440. style={{
  441. display: 'block',
  442. }}
  443. >
  444. 编辑
  445. </Button>
  446. </Tooltip>
  447. </div>
  448. );
  449. WrapDisabledElems.story = {
  450. name: 'wrap disabled elems',
  451. };
  452. export const InTable = () => (
  453. <div
  454. style={{
  455. marginTop: 50,
  456. }}
  457. >
  458. <InTableDemo />
  459. </div>
  460. );
  461. InTable.story = {
  462. name: 'in table',
  463. };
  464. export const _EdgeDemo = () => <EdgeDemo />;
  465. _EdgeDemo.story = {
  466. name: 'edge demo',
  467. };
  468. export const ScrollTooltipDemo = () => <ScrollTooltip />;
  469. ScrollTooltipDemo.story = {
  470. name: 'scroll demo and set popup container'
  471. }
  472. export const DangerousHtmlDemo = () => <DangerousHtml />;
  473. DangerousHtmlDemo.story = {
  474. name: 'in dangerous html'
  475. }
  476. export const ArrowPointAtCenterDemo = () => <ArrowPointAtCenter />;
  477. ArrowPointAtCenterDemo.story = {
  478. name: 'arrow point at center'
  479. }
  480. export const CustomContainerDemo = () => <CustomContainer />;
  481. CustomContainerDemo.story = {
  482. name: 'custom container'
  483. }
  484. export const ContainerPositionDemo = () => <ContainerPosition />;
  485. ContainerPositionDemo.story = {
  486. name: 'container observer'
  487. }
  488. export const QuickMoveMouse = () => {
  489. /**
  490. * mouseEnterDelay, mouseLeaveDelay 默认都为 50
  491. * mouseEnterDelay, mouseLeaveDelay 都为 0,快速滑动可能出现两个 tooltip 出现
  492. */
  493. const Demo = () => {
  494. const props = {
  495. mouseEnterDelay: 50,
  496. mouseLeaveDelay: 0,
  497. };
  498. return (
  499. <div className="demo">
  500. <div>
  501. <Tooltip content={'1'} {...props}>
  502. aaaaaaaaaaa
  503. </Tooltip>
  504. </div>
  505. <div>
  506. <Tooltip content={'2'} {...props}>
  507. bbbbbbbbbbb
  508. </Tooltip>
  509. </div>
  510. <div>
  511. <Tooltip content={'3'} {...props}>
  512. ccccccccccc
  513. </Tooltip>
  514. </div>
  515. <div>
  516. <Tooltip content={'4'} {...props}>
  517. aaaaaaaaaaa
  518. </Tooltip>
  519. </div>
  520. <div>
  521. <Tooltip content={'5'} {...props}>
  522. bbbbbbbbbbb
  523. </Tooltip>
  524. </div>
  525. <div>
  526. <Tooltip content={'6'} {...props}>
  527. ccccccccccc
  528. </Tooltip>
  529. </div>
  530. <div>
  531. <Tooltip content={'7'} {...props}>
  532. aaaaaaaaaaa
  533. </Tooltip>
  534. </div>
  535. <div>
  536. <Tooltip content={'8'} {...props}>
  537. bbbbbbbbbbb
  538. </Tooltip>
  539. </div>
  540. <div>
  541. <Tooltip content={'9'} {...props}>
  542. ccccccccccc
  543. </Tooltip>
  544. </div>
  545. </div>
  546. );
  547. };
  548. return <Demo />;
  549. };
  550. QuickMoveMouse.story = {
  551. name: '快速移动鼠标可见性'
  552. }
  553. export const MotionFalseFix1402 = () => {
  554. function Demo() {
  555. const Test = React.forwardRef((props, ref) => (
  556. <span {...props} ref={ref}>
  557. Test
  558. </span>
  559. ));
  560. return (
  561. <div>
  562. <Tooltip content={'hi bytedance'} motion={false}>
  563. <Test />
  564. </Tooltip>
  565. <br />
  566. <br />
  567. <Tooltip content={'hi bytedance'}>
  568. <Test />
  569. </Tooltip>
  570. </div>
  571. );
  572. }
  573. return <Demo />;
  574. };
  575. MotionFalseFix1402.story = {
  576. name: 'motion=false fix #1402',
  577. };
  578. export const DisabledWrapperCls = () => (
  579. <>
  580. <Tooltip wrapperClassName="test" content={'hi bytedance'}>
  581. <Button>按钮</Button>
  582. </Tooltip>
  583. <br />
  584. <br />
  585. <Tooltip wrapperClassName="test" content={'hi bytedance'}>
  586. <Button disabled>禁用的单个按钮</Button>
  587. </Tooltip>
  588. <br />
  589. <br />
  590. <Tooltip wrapperClassName="test" content={'hi bytedance'}>
  591. <Button>正常的多个按钮</Button>
  592. <Button>正常的多个按钮</Button>
  593. </Tooltip>
  594. <br />
  595. <br />
  596. <Tooltip wrapperClassName="test" content={'hi bytedance'}>
  597. <Select disabled placeholder="请选择业务线" style={{ width: 120 }}>
  598. <Select.Option value="abc">抖音</Select.Option>
  599. <Select.Option value="hotsoon">火山</Select.Option>
  600. <Select.Option value="jianying" disabled>
  601. 剪映
  602. </Select.Option>
  603. <Select.Option value="xigua">西瓜视频</Select.Option>
  604. </Select>
  605. </Tooltip>
  606. <br />
  607. <br />
  608. </>
  609. );
  610. DisabledWrapperCls.story = {
  611. name: 'disabledWrapperCls',
  612. };
  613. export const ShowArrow = () => {
  614. function Demo() {
  615. const Test = React.forwardRef((props, ref) => (
  616. <Tag {...props} ref={ref}>
  617. Test
  618. </Tag>
  619. ));
  620. return (
  621. <div>
  622. <h4>should show content and arrow when click</h4>
  623. <Tooltip style={{ maxWidth: 320 }} showArrow trigger='custom' visible content={'hi semi semi semi semi semi semi semi'} position='right'>
  624. <Test />
  625. </Tooltip>
  626. </div>
  627. );
  628. }
  629. return <Demo />;
  630. };
  631. ShowArrow.story = {
  632. name: 'showArrow',
  633. };
  634. export const OnClickOutSideDemo = () => {
  635. let [v, setV] = useState(false);
  636. let clickOutSide = () => {
  637. console.log('clickOutSide');
  638. setV(false);
  639. }
  640. return (
  641. <>
  642. <Tooltip onClickOutSide={() => clickOutSide()} content={'hi bytedance'} visible={v} trigger='custom'>
  643. <Button onClick={() => setV(true)}>按钮</Button>
  644. </Tooltip>
  645. <br />
  646. <br />
  647. <Tooltip onClickOutSide={() => console.log('clickOutSide')} content={'hi bytedance'} trigger='click'>
  648. <Button >单个按钮</Button>
  649. </Tooltip>
  650. </>
  651. );
  652. }
  653. OnClickOutSideDemo.story = {
  654. name: 'OnClickOutSide',
  655. };
  656. export const AutoAdjustWithSpacing = () => {
  657. const [height, setHeight] = useState(84);
  658. const [key, setKey] = useState(1);
  659. const initSpacing = 8;
  660. const [spacing, setSpacing] = useState(initSpacing);
  661. const change = (height, hasSpace) => {
  662. setHeight(height);
  663. hasSpace ? setSpacing(initSpacing) : setSpacing(0);
  664. setKey(Math.random());
  665. };
  666. return (
  667. <div className="demo1">
  668. <div>
  669. <Tooltip
  670. motion={false}
  671. rePosKey={key}
  672. // spacing={spacing}
  673. content={
  674. <article style={{ boxSizing: 'border-box', height: height }}>
  675. <p>hi bytedance, + padding 20</p>
  676. <p>hi bytedance</p>
  677. </article>
  678. }
  679. position="top"
  680. trigger="custom"
  681. visible={true}
  682. >
  683. <Tag>demo</Tag>
  684. </Tooltip>
  685. </div>
  686. <div style={{ marginTop: 200 }}>
  687. <Switch onChange={hasSpace => change(height, hasSpace)} checked={spacing === initSpacing ? true : false}></Switch>
  688. <InputNumber onChange={height => change(Number(height))} value={height} style={{ width: 200 }} />
  689. </div>
  690. </div>
  691. )
  692. };
  693. AutoAdjustWithSpacing.story = {
  694. name: 'AutoAdjustWithSpacing',
  695. };