Skip to content

Commit d336e6b

Browse files
committed
docs(tree): custom lines and double icon stories
1 parent cc17a88 commit d336e6b

File tree

1 file changed

+281
-0
lines changed

1 file changed

+281
-0
lines changed

.storybook/stories/Features/tree.story.js

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import * as React from 'react';
22
import { storiesOf } from '@storybook/react';
33

4+
import DescriptionOutlinedIcon from '@mui/icons-material/DescriptionOutlined';
5+
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
6+
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
47
import FolderIcon from '@mui/icons-material/Folder';
58
import FolderOpenIcon from '@mui/icons-material/FolderOpen';
69
import InsertDriveFileOutlinedIcon from '@mui/icons-material/InsertDriveFileOutlined';
@@ -16,6 +19,8 @@ import {
1619
} from '@table-library/react-table-library/table';
1720

1821
import { useTree, CellTree, TreeExpandClickTypes } from '@table-library/react-table-library/tree';
22+
import { useTheme } from '@table-library/react-table-library/theme';
23+
import { findNodeById } from '@table-library/react-table-library/common';
1924

2025
import { nodes } from '../data';
2126

@@ -395,6 +400,79 @@ storiesOf('Features/Tree', module)
395400
</Table>
396401
);
397402
})
403+
.add('double icon', () => {
404+
const data = { nodes };
405+
406+
const tree = useTree(
407+
data,
408+
{
409+
onChange: onTreeChange,
410+
},
411+
{
412+
treeIcon: {
413+
margin: '4px',
414+
iconDefault: (
415+
<div style={{ display: 'flex', alignItems: 'center' }}>
416+
<div style={{ height: '20px', width: '20px' }} />
417+
<DescriptionOutlinedIcon fontSize="small" />
418+
</div>
419+
),
420+
iconRight: (
421+
<div style={{ display: 'flex', alignItems: 'center' }}>
422+
<KeyboardArrowRightIcon fontSize="small" />
423+
<FolderIcon fontSize="small" />
424+
</div>
425+
),
426+
iconDown: (
427+
<div style={{ display: 'flex', alignItems: 'center' }}>
428+
<ExpandMoreIcon fontSize="small" />
429+
<FolderOpenIcon fontSize="small" />
430+
</div>
431+
),
432+
},
433+
},
434+
);
435+
436+
function onTreeChange(action, state) {
437+
console.log(action, state);
438+
}
439+
440+
return (
441+
<Table data={data} tree={tree}>
442+
{(tableList) => (
443+
<>
444+
<Header>
445+
<HeaderRow>
446+
<HeaderCell>Task</HeaderCell>
447+
<HeaderCell>Deadline</HeaderCell>
448+
<HeaderCell>Type</HeaderCell>
449+
<HeaderCell>Complete</HeaderCell>
450+
<HeaderCell>Tasks</HeaderCell>
451+
</HeaderRow>
452+
</Header>
453+
454+
<Body>
455+
{tableList.map((item) => (
456+
<Row key={item.id} item={item}>
457+
<CellTree item={item}>{item.name}</CellTree>
458+
<Cell>
459+
{item.deadline.toLocaleDateString('en-US', {
460+
year: 'numeric',
461+
month: '2-digit',
462+
day: '2-digit',
463+
})}
464+
</Cell>
465+
<Cell>{item.type}</Cell>
466+
<Cell>{item.isComplete.toString()}</Cell>
467+
<Cell>{item.nodes?.length}</Cell>
468+
</Row>
469+
))}
470+
</Body>
471+
</>
472+
)}
473+
</Table>
474+
);
475+
})
398476
.add('no icon margin', () => {
399477
const data = { nodes };
400478

@@ -606,4 +684,207 @@ storiesOf('Features/Tree', module)
606684
)}
607685
</Table>
608686
);
687+
})
688+
.add('custom lines', () => {
689+
const data = { nodes };
690+
691+
const isLastChild = (nodes, node) => {
692+
const parentNode = findNodeById(
693+
nodes,
694+
node.parentNode?.id ? node.parentNode.id.toString() : null,
695+
);
696+
697+
if (!parentNode && nodes[nodes.length - 1].id === node.id) {
698+
return true;
699+
} else if (!parentNode && nodes[nodes.length - 1].id !== node.id) {
700+
return false;
701+
}
702+
703+
if (!parentNode?.nodes) return true;
704+
return parentNode?.nodes[parentNode?.nodes.length - 1].id === node.id;
705+
};
706+
707+
const isFirstChild = (nodes, node) => {
708+
return nodes[0].id === node.id;
709+
};
710+
711+
const theme = useTheme({
712+
Cell: `
713+
height: 40px;
714+
715+
position: relative;
716+
717+
&:nth-of-type(1) {
718+
margin-left: 8px;
719+
padding-left: 8px;
720+
}
721+
722+
& .line {
723+
background-color: #0097e0;
724+
}
725+
726+
&:first-of-type div {
727+
max-width: 100%;
728+
729+
height: 100%;
730+
display: flex;
731+
align-items: center;
732+
}
733+
734+
& .line-icon-container > * {
735+
position: absolute;
736+
pointer-events: none;
737+
}
738+
`,
739+
});
740+
741+
const tree = useTree(
742+
data,
743+
{
744+
onChange: onTreeChange,
745+
},
746+
{
747+
treeIcon: {
748+
margin: '4px',
749+
iconDefault: (
750+
<LineIcon>
751+
<InsertDriveFileOutlinedIcon fontSize="small" />
752+
</LineIcon>
753+
),
754+
iconRight: (
755+
<LineIcon>
756+
<FolderIcon fontSize="small" />
757+
</LineIcon>
758+
),
759+
iconDown: (
760+
<LineIcon>
761+
<FolderOpenIcon fontSize="small" />
762+
</LineIcon>
763+
),
764+
},
765+
},
766+
);
767+
768+
function onTreeChange(action, state) {
769+
console.log(action, state);
770+
}
771+
772+
return (
773+
<Table data={data} theme={theme} tree={tree}>
774+
{(tableList) => (
775+
<>
776+
<Header>
777+
<HeaderRow>
778+
<HeaderCell>Task</HeaderCell>
779+
<HeaderCell>Deadline</HeaderCell>
780+
<HeaderCell>Type</HeaderCell>
781+
<HeaderCell>Complete</HeaderCell>
782+
<HeaderCell>Tasks</HeaderCell>
783+
</HeaderRow>
784+
</Header>
785+
786+
<Body>
787+
{tableList.map((item, index) => (
788+
<Row key={item.id} item={item}>
789+
<CellTree item={item}>
790+
<Line
791+
isFirst={isFirstChild(data.nodes, item)}
792+
isLast={isLastChild(data.nodes, item)}
793+
treeXLevel={item.treeXLevel}
794+
>
795+
{item.name}
796+
</Line>
797+
</CellTree>
798+
<Cell>
799+
{item.deadline.toLocaleDateString('en-US', {
800+
year: 'numeric',
801+
month: '2-digit',
802+
day: '2-digit',
803+
})}
804+
</Cell>
805+
<Cell>{item.type}</Cell>
806+
<Cell>{item.isComplete.toString()}</Cell>
807+
<Cell>{item.nodes?.length}</Cell>
808+
</Row>
809+
))}
810+
</Body>
811+
</>
812+
)}
813+
</Table>
814+
);
609815
});
816+
817+
const LineIcon = ({ children }) => (
818+
<div
819+
className="line-icon-container"
820+
style={{
821+
zIndex: 2,
822+
width: 24,
823+
height: 24,
824+
color: '#5472d3',
825+
display: 'flex',
826+
justifyContent: 'center',
827+
alignItems: 'center',
828+
position: 'relative',
829+
pointerEvents: 'none',
830+
}}
831+
>
832+
<div style={{ height: '20px', width: '20px', backgroundColor: '#ffffff' }} />
833+
{children}
834+
</div>
835+
);
836+
837+
const Line = ({ isFirst, isLast, treeXLevel, children }) => {
838+
return (
839+
<>
840+
<div
841+
style={{
842+
zIndex: 1,
843+
display: 'inline-block',
844+
width: '9px',
845+
height: '40px',
846+
pointerEvents: 'none',
847+
}}
848+
>
849+
<div
850+
className="line"
851+
style={{
852+
position: 'absolute',
853+
top: isFirst ? '20px' : '0',
854+
left: `${19 + treeXLevel * 20}px`,
855+
width: '1px',
856+
height: isLast ? '20px' : '40px',
857+
}}
858+
/>
859+
<div
860+
className="line"
861+
style={{
862+
position: 'absolute',
863+
top: '20px',
864+
left: `${19 + treeXLevel * 20}px`,
865+
width: '18px',
866+
height: '1px',
867+
}}
868+
/>
869+
</div>
870+
871+
<span
872+
style={{
873+
display: 'flex',
874+
alignItems: 'center',
875+
minWidth: 0,
876+
}}
877+
>
878+
<span
879+
style={{
880+
whiteSpace: 'nowrap',
881+
textOverflow: 'ellipsis',
882+
overflow: 'hidden',
883+
}}
884+
>
885+
{children}
886+
</span>
887+
</span>
888+
</>
889+
);
890+
};

0 commit comments

Comments
 (0)