collapsible.stories.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. /* argus-disable unPkgSensitiveInfo */
  2. import React, { useState } from 'react';
  3. import { storiesOf } from '@storybook/react';
  4. import { Button, CheckboxGroup, Upload, Table, Collapse, Tabs } from '../../index';
  5. import Collapsible from '..';
  6. import NestedDemo from './Nested';
  7. import { IconChevronDown, IconChevronRight, IconUpload } from '@douyinfe/semi-icons';
  8. const TabPane = Tabs.TabPane;
  9. const stories = storiesOf('Collapsible', module); // stories.addDecorator(withKnobs);;
  10. class Demo extends React.Component {
  11. state = {
  12. isOpen: false,
  13. };
  14. toggle = () => {
  15. this.setState({
  16. isOpen: !this.state.isOpen,
  17. });
  18. };
  19. render() {
  20. const { isOpen } = this.state;
  21. const collapsed = (
  22. <ul>
  23. <li>
  24. <p>Semi Design 以内容优先进行设计。</p>
  25. </li>
  26. <li>
  27. <p>更容易地自定义主题。</p>
  28. </li>
  29. <li>
  30. <p>适用国际化场景。</p>
  31. </li>
  32. <li>
  33. <p>效率场景加入人性化关怀。</p>
  34. </li>
  35. </ul>
  36. );
  37. return (
  38. <div>
  39. <Button onClick={() => this.toggle()}>显示更多</Button>
  40. <Collapsible isOpen={isOpen}>{collapsed}</Collapsible>
  41. </div>
  42. );
  43. }
  44. }
  45. stories.add('regular collapsible', () => <Demo />);
  46. class DemoDOM extends React.Component {
  47. state = {
  48. isOpen: false,
  49. };
  50. toggle = () => {
  51. this.setState({
  52. isOpen: !this.state.isOpen,
  53. });
  54. };
  55. render() {
  56. const { isOpen } = this.state;
  57. const collapsed = (
  58. <ul>
  59. <li>
  60. <p>Semi Design 以内容优先进行设计。</p>
  61. </li>
  62. <li>
  63. <p>更容易地自定义主题。</p>
  64. </li>
  65. <li>
  66. <p>适用国际化场景。</p>
  67. </li>
  68. <li>
  69. <p>效率场景加入人性化关怀。</p>
  70. </li>
  71. </ul>
  72. );
  73. return (
  74. <div>
  75. <Button onClick={() => this.toggle()}>显示更多</Button>
  76. <Collapsible keepDOM isOpen={isOpen}>
  77. {collapsed}
  78. </Collapsible>
  79. </div>
  80. );
  81. }
  82. }
  83. stories.add('keepDOM', () => <DemoDOM />);
  84. class DefaultOPen extends React.Component {
  85. state = {
  86. isOpen: true,
  87. };
  88. toggle = () => {
  89. this.setState({
  90. isOpen: !this.state.isOpen,
  91. });
  92. };
  93. render() {
  94. const { isOpen } = this.state;
  95. const collapsed = (
  96. <ul>
  97. <li>
  98. <p>Semi Design 以内容优先进行设计。</p>
  99. </li>
  100. <li>
  101. <p>更容易地自定义主题。</p>
  102. </li>
  103. <li>
  104. <p>适用国际化场景。</p>
  105. </li>
  106. <li>
  107. <p>效率场景加入人性化关怀。</p>
  108. </li>
  109. </ul>
  110. );
  111. return (
  112. <div>
  113. <Button onClick={() => this.toggle()}>toggle</Button>
  114. <Collapsible isOpen={isOpen}>{collapsed}</Collapsible>
  115. </div>
  116. );
  117. }
  118. }
  119. stories.add('Default Open', () => <DefaultOPen />);
  120. stories.add('nested collapsible', () => <NestedDemo />);
  121. class Wrap extends React.Component {
  122. constructor(props) {
  123. super(props);
  124. this.state = {
  125. isOpen: props.isOpen,
  126. options: [
  127. {
  128. label: '抖音',
  129. value: 'dy',
  130. },
  131. {
  132. label: '火山',
  133. value: 'hotsoon',
  134. },
  135. {
  136. label: '皮皮虾',
  137. value: 'pipixia',
  138. },
  139. {
  140. label: '今日头条',
  141. value: 'toutiao',
  142. },
  143. ],
  144. values: [],
  145. };
  146. this.toggle = this.toggle.bind(this);
  147. this.onChange = this.onChange.bind(this);
  148. }
  149. toggle() {
  150. this.setState({
  151. isOpen: !this.state.isOpen,
  152. });
  153. }
  154. onChange(values) {
  155. this.setState({
  156. values,
  157. });
  158. }
  159. render() {
  160. const { isOpen, options, values } = this.state;
  161. return (
  162. <>
  163. <div onClick={this.toggle}>
  164. {isOpen ? <IconChevronDown /> : <IconChevronRight />}
  165. 权限点
  166. <span>
  167. {values.length}/{options.length}
  168. </span>
  169. </div>
  170. <Collapse defaultActiveKey="1" motion={false}>
  171. <Collapse.Panel header="This is panel header 1" itemKey="1">
  172. <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
  173. </Collapse.Panel>
  174. <Collapse.Panel header="This is panel header 2" itemKey="2">
  175. <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
  176. </Collapse.Panel>
  177. <Collapse.Panel header="This is panel header 3" itemKey="3">
  178. <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
  179. </Collapse.Panel>
  180. </Collapse>
  181. {/* <Collapsible isOpen={isOpen}>
  182. <div style={{ height: '40px' }}>
  183. <CheckboxGroup options={options} direction="horizontal" onChange={this.onChange} value={values} />
  184. </div>
  185. </Collapsible> */}
  186. </>
  187. );
  188. }
  189. }
  190. stories.add('collapsible test', () => <Wrap />);
  191. class App extends React.Component {
  192. render() {
  193. const expandColumns = [
  194. {
  195. title: 'Name',
  196. dataIndex: 'name',
  197. key: 'name',
  198. },
  199. {
  200. title: 'Age',
  201. dataIndex: 'age',
  202. key: 'age',
  203. },
  204. {
  205. title: 'Address',
  206. dataIndex: 'address',
  207. key: 'address',
  208. },
  209. {
  210. title: 'Action',
  211. dataIndex: '',
  212. key: 'x',
  213. render: () => <a>Delete</a>,
  214. },
  215. ];
  216. const rowSelection = {
  217. onChange: (selectedRowKeys, selectedRows) => {
  218. // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  219. },
  220. getCheckboxProps: record => ({
  221. disabled: record.name === 'Michael James',
  222. // Column configuration not to be checked
  223. name: record.name,
  224. }),
  225. };
  226. const expandData = [
  227. {
  228. name: 'John Brown',
  229. age: 32,
  230. address: 'New York No. 1 Lake Park',
  231. description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
  232. },
  233. {
  234. name: 'Jim Green',
  235. age: 42,
  236. address: 'London No. 1 Lake Park',
  237. description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
  238. },
  239. {
  240. name: 'Joe Black',
  241. age: 32,
  242. address: (
  243. <Collapse defaultActiveKey="1" motion={false}>
  244. <Collapse.Panel header="This is panel header 1" itemKey="1">
  245. <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
  246. </Collapse.Panel>
  247. <Collapse.Panel header="This is panel header 2" itemKey="2">
  248. <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
  249. </Collapse.Panel>
  250. <Collapse.Panel header="This is panel header 3" itemKey="3">
  251. <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
  252. </Collapse.Panel>
  253. </Collapse>
  254. ),
  255. description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.',
  256. },
  257. ];
  258. const expandRowRender = (record, index) => <Wrap isOpen={true} />;
  259. return (
  260. <Table
  261. rowKey={'name'}
  262. columns={expandColumns}
  263. rowSelection={rowSelection}
  264. expandedRowRender={expandRowRender}
  265. dataSource={expandData}
  266. />
  267. );
  268. }
  269. }
  270. stories.add('collapsible in table', () => <App />);
  271. class InTab extends React.Component {
  272. constructor() {
  273. super();
  274. this.state = {
  275. isOpenFirst: false,
  276. isOpenSecond: false,
  277. };
  278. }
  279. render() {
  280. const { isOpenFirst, isOpenSecond } = this.state;
  281. return (
  282. <div>
  283. <Tabs
  284. onTabClick={e =>
  285. this.setState({
  286. active: e,
  287. })
  288. }
  289. >
  290. <TabPane tab="第一" itemKey="1">
  291. <h3>第一个tabpane</h3>
  292. <Button
  293. onClick={() => {
  294. this.setState({
  295. isOpenFirst: !isOpenFirst,
  296. });
  297. }}
  298. >
  299. 开关
  300. </Button>
  301. <Collapsible isOpen={isOpenFirst}>第一个tabpane下的collapsible的open状态正常</Collapsible>
  302. </TabPane>
  303. <TabPane tab="第二" itemKey="2">
  304. <h3>第二个tabpane</h3>
  305. <Button
  306. onClick={() => {
  307. this.setState({
  308. isOpenSecond: !isOpenSecond,
  309. });
  310. }}
  311. >
  312. 开关
  313. </Button>
  314. <Collapsible isOpen={isOpenSecond}>第二个tabpane下的collapsibleopen状态异常</Collapsible>
  315. </TabPane>
  316. </Tabs>
  317. </div>
  318. );
  319. }
  320. }
  321. stories.add('collapsible in tab', () => <InTab />);
  322. class WithUpload extends React.Component {
  323. constructor(props) {
  324. super(props);
  325. this.state = {
  326. isOpen: true,
  327. };
  328. this.toggle = this.toggle.bind(this);
  329. this.action = '//semi.design/api/upload/';
  330. this.defaultFileList = [
  331. {
  332. preview: false,
  333. name: '2D (2).ecpj',
  334. status: 'success',
  335. uid: 'd116a179410eb0ca18e66074509bde93-0',
  336. url: 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
  337. },
  338. {
  339. preview: false,
  340. name: '2D-sticker-temp.psd',
  341. status: 'success',
  342. uid: 'b7d579069320590ba4b128672eedbae2-1',
  343. url: 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
  344. },
  345. {
  346. preview: false,
  347. name: '2D-sticker-temp (1).psd',
  348. status: 'success',
  349. uid: 'b7d579069320590ba4b128672eedbae2-2',
  350. url: 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
  351. },
  352. ];
  353. }
  354. toggle() {
  355. this.setState({
  356. isOpen: !this.state.isOpen,
  357. });
  358. }
  359. render() {
  360. const { isOpen } = this.state;
  361. return (
  362. <div>
  363. <Collapsible isOpen={isOpen} collapseHeight={120}>
  364. <Upload
  365. dragable={true}
  366. name="file" // accept={ALLOW_FILE}
  367. defaultFileList={[
  368. {
  369. preview: false,
  370. name: '2D (2).ecpj',
  371. status: 'success',
  372. uid: 'd116a179410eb0ca18e66074509bde93-0',
  373. url:
  374. 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
  375. },
  376. {
  377. preview: false,
  378. name: '2D-sticker-temp.psd',
  379. status: 'success',
  380. uid: 'b7d579069320590ba4b128672eedbae2-1',
  381. url:
  382. 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
  383. },
  384. {
  385. preview: false,
  386. name: '2D-sticker-temp (1).psd',
  387. status: 'success',
  388. uid: 'b7d579069320590ba4b128672eedbae2-2',
  389. url:
  390. 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
  391. },
  392. ]}
  393. dragMainText="点击上传文件或拖拽文件到这里"
  394. dragSubText="图片、PDF、PPT、Word、视频等"
  395. onError={this.uploadError}
  396. onSuccess={(...args) => this.uploadSuccess(i, ...args)}
  397. onRemove={(...args) => this.onRemoveFile(i, ...args)}
  398. onProgress={() =>
  399. this.setState({
  400. fileLoading: true,
  401. })
  402. }
  403. >
  404. <Button icon={<IconUpload />} theme="light">
  405. 点击上传
  406. </Button>
  407. </Upload>
  408. </Collapsible>
  409. <Button onClick={this.toggle}>{isOpen ? '剩余1项' : '展开'}</Button>
  410. </div>
  411. );
  412. }
  413. }
  414. stories.add('collapsible with Upload', () => <WithUpload />);
  415. class CusHeight extends React.Component {
  416. constructor(props) {
  417. super(props);
  418. this.state = {
  419. isOpen: false,
  420. };
  421. this.toggle = this.toggle.bind(this);
  422. }
  423. toggle() {
  424. this.setState({
  425. isOpen: !this.state.isOpen,
  426. });
  427. }
  428. render() {
  429. const { isOpen } = this.state;
  430. const maskStyle = isOpen
  431. ? {}
  432. : {
  433. WebkitMaskImage:
  434. 'linear-gradient(to bottom, black 0%, rgba(0, 0, 0, 1) 60%, rgba(0, 0, 0, 0.2) 80%, transparent 100%)',
  435. };
  436. const collapsed = (
  437. <ul>
  438. <li>
  439. <p>Semi Design 以内容优先进行设计。</p>
  440. </li>
  441. <li>
  442. <p>更容易地自定义主题。</p>
  443. </li>
  444. <li>
  445. <p>适用国际化场景。</p>
  446. </li>
  447. <li>
  448. <p>效率场景加入人性化关怀。</p>
  449. </li>
  450. </ul>
  451. );
  452. const linkStyle = {
  453. position: 'absolute',
  454. left: 0,
  455. right: 0,
  456. textAlign: 'center',
  457. bottom: -10,
  458. fontWeight: 700,
  459. cursor: 'pointer',
  460. };
  461. console.log('out state', isOpen);
  462. return (
  463. <>
  464. <Button onClick={this.toggle}>Toggle</Button>
  465. <div
  466. style={{
  467. position: 'relative',
  468. }}
  469. >
  470. <Collapsible
  471. isOpen={isOpen}
  472. collapseHeight={40}
  473. style={{ ...maskStyle }}
  474. onInnerStateOpen={bool => {
  475. if (isOpen !== bool) {
  476. this.setState({
  477. isOpen: bool,
  478. });
  479. }
  480. }}
  481. >
  482. {collapsed}
  483. </Collapsible>
  484. {isOpen ? null : (
  485. <a onClick={this.toggle} style={{ ...linkStyle }}>
  486. + Show More
  487. </a>
  488. )}
  489. </div>
  490. </>
  491. );
  492. }
  493. }
  494. stories.add('collapse height', () => <CusHeight />);
  495. const Child = ({ onClick }) => {
  496. const [isCOpen, setIsCOpen] = useState(false);
  497. return (
  498. <div>
  499. <div
  500. style={{
  501. display: isCOpen ? 'block' : 'none',
  502. height: 200,
  503. background: 'green',
  504. }}
  505. >
  506. child
  507. </div>
  508. <Button
  509. onClick={() => {
  510. setIsCOpen(!isCOpen);
  511. onClick();
  512. }}
  513. >
  514. Toggle
  515. </Button>
  516. </div>
  517. );
  518. }; // dynamic update content, children comp need to separate from parent to avoid rerender of entire comp
  519. const DynamDemo = () => {
  520. const [isOpen, setIsOpen] = useState(true);
  521. const [reCalcKey, setReCalcKey] = useState(0);
  522. return (
  523. <div>
  524. <Button onClick={() => setIsOpen(!isOpen)}>折叠</Button>
  525. <Collapsible isOpen={isOpen}>
  526. <div>
  527. <div
  528. style={{
  529. height: 200,
  530. background: 'blue',
  531. }}
  532. >
  533. father
  534. </div>
  535. <Child onClick={() => setReCalcKey(reCalcKey + 1)} />
  536. </div>
  537. </Collapsible>
  538. </div>
  539. );
  540. };
  541. stories.add('dynamic collapsible', () => <DynamDemo />);