diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/Sidebar/Backlinks.tsx | 2 | ||||
-rw-r--r-- | components/Sidebar/Note.tsx | 2 | ||||
-rw-r--r-- | components/Sidebar/TagBar.tsx | 79 | ||||
-rw-r--r-- | components/Sidebar/Toolbar.tsx | 2 | ||||
-rw-r--r-- | components/Sidebar/index.tsx | 127 | ||||
-rw-r--r-- | components/TagMenu.tsx | 117 | ||||
-rw-r--r-- | components/Tweaks/ColorMenu.tsx | 73 | ||||
-rw-r--r-- | components/Tweaks/index.tsx | 2 | ||||
-rw-r--r-- | components/config.ts | 4 | ||||
-rw-r--r-- | components/contextmenu.tsx | 227 |
10 files changed, 452 insertions, 183 deletions
diff --git a/components/Sidebar/Backlinks.tsx b/components/Sidebar/Backlinks.tsx index 68ab551..d82fbba 100644 --- a/components/Sidebar/Backlinks.tsx +++ b/components/Sidebar/Backlinks.tsx @@ -43,7 +43,7 @@ export const Backlinks = (props: BacklinksProps) => { <Box> <Heading pt={4}>{`Backlinks (${backLinks.length})`}</Heading> <VStack - pt={2} + py={2} spacing={3} alignItems="start" divider={<StackDivider borderColor="gray.500" />} diff --git a/components/Sidebar/Note.tsx b/components/Sidebar/Note.tsx index e425559..37e836d 100644 --- a/components/Sidebar/Note.tsx +++ b/components/Sidebar/Note.tsx @@ -35,7 +35,7 @@ export const Note = (props: NoteProps) => { <Box pr={8} overflow="scroll" - height="85%" + height="100%" className="org" sx={{ ...noteStyle, diff --git a/components/Sidebar/TagBar.tsx b/components/Sidebar/TagBar.tsx new file mode 100644 index 0000000..0fe0a18 --- /dev/null +++ b/components/Sidebar/TagBar.tsx @@ -0,0 +1,79 @@ +import React from 'react' +import { initialFilter, TagColors } from '../config' +import { NodeObject } from 'force-graph' +import { OrgRoamNode } from '../../api' +import { ViewIcon, ViewOffIcon } from '@chakra-ui/icons' +import { Flex, Tag, TagLabel, TagRightIcon } from '@chakra-ui/react' + +export interface TagBarProps { + filter: typeof initialFilter + setFilter: any + tagColors: TagColors + setTagColors: any + openContextMenu: any + previewNode: NodeObject +} + +export const TagBar = (props: TagBarProps) => { + const { filter, setFilter, tagColors, setTagColors, openContextMenu, previewNode } = props + + const node = previewNode as OrgRoamNode + if (!node.tags || node?.tags[0] === null) { + return null + } + return ( + <Flex mb={2} flexWrap="wrap"> + {node?.tags?.map((tag: string) => { + const bl: string[] = filter.tagsBlacklist ?? [] + const wl: string[] = filter.tagsWhitelist ?? [] + const blackList: boolean = bl.includes(tag) + const whiteList = wl.includes(tag) + return ( + <Tag + tabIndex={0} + mr={2} + mt={2} + onContextMenu={(e) => { + e.preventDefault() + openContextMenu(tag, e) + }} + cursor="pointer" + onClick={() => { + if (blackList) { + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsBlacklist: filter.tagsBlacklist.filter((t) => t !== tag), + tagsWhitelist: [...filter.tagsWhitelist, tag], + })) + return + } + if (whiteList) { + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsWhitelist: filter.tagsWhitelist.filter((t) => t !== tag), + })) + return + } + + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsBlacklist: [...filter.tagsBlacklist, tag], + })) + }} + size="sm" + key={tag} + variant="outline" + colorScheme={tagColors[tag]?.replaceAll(/(.*?)\..*/g, '$1') || undefined} + > + <TagLabel>{tag}</TagLabel> + {blackList ? ( + <TagRightIcon as={ViewOffIcon} /> + ) : whiteList ? ( + <TagRightIcon as={ViewIcon} /> + ) : null} + </Tag> + ) + })} + </Flex> + ) +} diff --git a/components/Sidebar/Toolbar.tsx b/components/Sidebar/Toolbar.tsx index 8741da5..6cbecae 100644 --- a/components/Sidebar/Toolbar.tsx +++ b/components/Sidebar/Toolbar.tsx @@ -38,7 +38,7 @@ export const Toolbar = (props: ToolbarProps) => { nextPreviewNode, } = props return ( - <Flex pb={3} alignItems="center" justifyContent="space-between" pl={1} pr={1}> + <Flex flex="0 1 40px" pb={3} alignItems="center" justifyContent="space-between" pl={1} pr={1}> <Flex> <ButtonGroup isAttached> <Tooltip label="Go backward"> diff --git a/components/Sidebar/index.tsx b/components/Sidebar/index.tsx index cbc0cc9..957669c 100644 --- a/components/Sidebar/index.tsx +++ b/components/Sidebar/index.tsx @@ -1,12 +1,33 @@ import React, { useContext, useEffect, useRef, useState } from 'react' import { Toolbar } from './Toolbar' +import { TagBar } from './TagBar' import { Note } from './Note' -import { Button, Slide, VStack, Flex, Heading, Box, IconButton, Tooltip } from '@chakra-ui/react' +import { + Button, + Slide, + VStack, + Flex, + Heading, + Box, + IconButton, + Tooltip, + HStack, + TagLabel, + Tag, + TagRightIcon, +} from '@chakra-ui/react' import { Collapse } from './Collapse' import { Scrollbars } from 'react-custom-scrollbars-2' -import { ChevronLeftIcon, ChevronRightIcon, CloseIcon, HamburgerIcon } from '@chakra-ui/icons' +import { + ChevronLeftIcon, + ChevronRightIcon, + CloseIcon, + HamburgerIcon, + ViewIcon, + ViewOffIcon, +} from '@chakra-ui/icons' import { BiDotsVerticalRounded, BiFile, BiNetworkChart } from 'react-icons/bi' import { BsReverseLayoutSidebarInsetReverse } from 'react-icons/bs' @@ -16,6 +37,7 @@ import { ThemeContext } from '../../util/themecontext' import { LinksByNodeId, NodeByCite, NodeById, Scope } from '../../pages/index' import { Resizable } from 're-resizable' import { usePersistantState } from '../../util/persistant-state' +import { initialFilter, TagColors } from '../config' export interface SidebarProps { isOpen: boolean @@ -36,6 +58,10 @@ export interface SidebarProps { scope: Scope setScope: any windowWidth: number + filter: typeof initialFilter + setFilter: any + tagColors: TagColors + setTagColors: any } const Sidebar = (props: SidebarProps) => { @@ -58,6 +84,10 @@ const Sidebar = (props: SidebarProps) => { scope, setScope, windowWidth, + filter, + setFilter, + tagColors, + setTagColors, } = props const { highlightColor } = useContext(ThemeContext) @@ -90,7 +120,7 @@ const Sidebar = (props: SidebarProps) => { style={{ height: '100vh' }} > <Resizable - size={{ height: '100%', width: sidebarWidth }} + size={{ height: '100vh', width: sidebarWidth }} onResizeStop={(e, direction, ref, d) => { setSidebarWidth((curr: number) => curr + d.width) }} @@ -107,22 +137,24 @@ const Sidebar = (props: SidebarProps) => { minWidth="220px" maxWidth={windowWidth - 200} > - <Box pl={2} color="black" h="100%" bg="alt.100" width="100%"> + <Flex flexDir="column" h="100vh" pl={2} color="black" bg="alt.100" width="100%"> <Flex - whiteSpace="nowrap" - overflow="hidden" - textOverflow="ellipsis" + //whiteSpace="nowrap" + // overflow="hidden" + // textOverflow="ellipsis" pl={4} alignItems="center" color="black" width="100%" > - <BiFile - onContextMenu={(e) => { - e.preventDefault() - openContextMenu(previewNode, e) - }} - /> + <Flex flexShrink={0}> + <BiFile + onContextMenu={(e) => { + e.preventDefault() + openContextMenu(previewNode, e) + }} + /> + </Flex> <Flex whiteSpace="nowrap" textOverflow="ellipsis" @@ -177,39 +209,42 @@ const Sidebar = (props: SidebarProps) => { nextPreviewNode, }} /> - <Scrollbars - //autoHeight - //autoHeightMax={600} - autoHide - renderThumbVertical={({ style, ...props }) => ( - <Box - style={{ - ...style, - borderRadius: 10, - backgroundColor: highlightColor, - }} - color="alt.100" - {...props} - /> - )} - > - <VStack height="100%" alignItems="left" bg="alt.100" paddingLeft={4}> - <Note - {...{ - setPreviewNode, - previewNode, - nodeById, - nodeByCite, - setSidebarHighlightedNode, - justification, - justificationList, - linksByNodeId, - openContextMenu, - }} - /> - </VStack> - </Scrollbars> - </Box> + {/* <Scrollbars + * //autoHeight + * autoHeightMax={600} + * autoHide + * renderThumbVertical={({ style, ...props }) => ( + * <Box + * style={{ + * ...style, + * borderRadius: 0, + * // backgroundColor: highlightColor, + * }} + * //color="alt.100" + * {...props} + * /> + * )} + * > */} + <VStack flexGrow={1} overflow="scroll" alignItems="left" bg="alt.100" paddingLeft={4}> + <TagBar + {...{ filter, setFilter, tagColors, setTagColors, openContextMenu, previewNode }} + /> + <Note + {...{ + setPreviewNode, + previewNode, + nodeById, + nodeByCite, + setSidebarHighlightedNode, + justification, + justificationList, + linksByNodeId, + openContextMenu, + }} + /> + </VStack> + {/*</Scrollbars>*/} + </Flex> </Resizable> </Collapse> ) diff --git a/components/TagMenu.tsx b/components/TagMenu.tsx new file mode 100644 index 0000000..432e9a2 --- /dev/null +++ b/components/TagMenu.tsx @@ -0,0 +1,117 @@ +import { MinusIcon, AddIcon, ViewOffIcon, ViewIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Button, + Flex, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + useDisclosure, +} from '@chakra-ui/react' +import React from 'react' +import { colorList, initialFilter, TagColors } from './config' +import { Collapse } from './Sidebar/Collapse' +import { ColorMenu } from './Tweaks/ColorMenu' + +export interface TagMenuProps { + setTagColors: any + tagColors: TagColors + setFilter: any + filter: typeof initialFilter + target: string | null +} + +export const TagMenu = (props: TagMenuProps) => { + const { setTagColors, setFilter, filter, tagColors, target } = props + const bl: string[] = filter.tagsBlacklist + const wl: string[] = filter.tagsWhitelist + const blacklist = bl.indexOf(target as string) > -1 + const whitelist = wl.indexOf(target as string) > -1 + const colors = useDisclosure() + return ( + <> + <MenuItem + icon={ + <Box + bgColor={tagColors[target as string]} + borderRadius="sm" + height={3} + width={3} + borderColor={tagColors[target as string] || 'gray.600'} + borderWidth={1} + ></Box> + } + closeOnSelect={false} + onClick={colors.onToggle} + > + <Text>Change color</Text> + </MenuItem> + <Collapse in={colors.isOpen}> + <Flex ml={2} mt={2} flexWrap="wrap"> + {colorList.map((color: string) => ( + <Box key={color}> + <Box + tabIndex={0} + cursor="pointer" + onClick={() => + setTagColors({ + ...tagColors, + [target as string]: color, + }) + } + bgColor={color} + m={1} + borderRadius="sm" + height={3} + width={3} + ></Box> + </Box> + ))} + </Flex> + </Collapse> + {!whitelist && ( + <MenuItem + onClick={() => { + if (!blacklist) { + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsBlacklist: [...filter.tagsBlacklist, target], + })) + return + } + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsBlacklist: filter.tagsBlacklist.filter((t) => t !== target), + })) + }} + icon={blacklist ? <MinusIcon /> : <ViewOffIcon />} + > + {blacklist ? 'Remove from blacklist' : 'Add to blacklist'} + </MenuItem> + )} + {!blacklist && ( + <MenuItem + onClick={() => { + if (!whitelist) { + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsWhitelist: [...filter.tagsWhitelist, target], + })) + return + } + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsWhitelist: filter.tagsWhitelist.filter((t) => t !== target), + })) + }} + icon={whitelist ? <MinusIcon /> : <ViewIcon />} + > + {whitelist ? 'Remove from whitelist' : 'Add to whitelist'} + </MenuItem> + )} + </> + ) +} diff --git a/components/Tweaks/ColorMenu.tsx b/components/Tweaks/ColorMenu.tsx index 3d90e36..b87f76b 100644 --- a/components/Tweaks/ColorMenu.tsx +++ b/components/Tweaks/ColorMenu.tsx @@ -9,6 +9,9 @@ import { MenuItem, MenuList, Portal, + PopoverTrigger, + PopoverContent, + Popover, } from '@chakra-ui/react' import React, { useCallback } from 'react' import { initialVisuals } from '../config' @@ -19,10 +22,11 @@ export interface ColorMenuProps { value: string visValue: string setVisuals?: any + noEmpty?: boolean } export const ColorMenu = (props: ColorMenuProps) => { - const { label, colorList, value, visValue, setVisuals } = props + const { label, colorList, value, visValue, setVisuals, noEmpty } = props const clickCallback = useCallback( (color) => @@ -37,35 +41,48 @@ export const ColorMenu = (props: ColorMenuProps) => { return ( <Flex alignItems="center" justifyContent="space-between"> <Text>{label}</Text> - <Menu isLazy placement="right"> - <MenuButton as={Button} colorScheme="" color="black" rightIcon={<ChevronDownIcon />}> - {<Box bgColor={visValue} borderRadius="sm" height={6} width={6}></Box>} - </MenuButton> + <Popover isLazy placement="right"> + <PopoverTrigger> + <Button colorScheme="" color="black" rightIcon={<ChevronDownIcon />}> + {<Box bgColor={visValue} borderRadius="sm" height={6} width={6}></Box>} + </Button> + </PopoverTrigger> <Portal> - {' '} - <MenuList minW={10} zIndex="popover" bgColor="gray.200"> - <MenuItem - onClick={() => clickCallback('')} - justifyContent="space-between" - alignItems="center" - display="flex" - > - <Box height={6} width={6}></Box> - </MenuItem> - {colorList.map((color: string) => ( - <MenuItem - key={color} - onClick={() => clickCallback(color)} - justifyContent="space-between" - alignItems="center" - display="flex" - > - <Box bgColor={color} borderRadius="sm" height={6} width={6}></Box> - </MenuItem> - ))} - </MenuList> + <PopoverContent zIndex="tooltip" maxW={36} position="relative"> + <Flex flexWrap="wrap" bgColor="gray.200"> + {!noEmpty && ( + <Box + onClick={() => clickCallback('')} + justifyContent="space-between" + alignItems="center" + display="flex" + m={1} + > + <Box + height={6} + width={6} + borderColor="gray.600" + borderRadius="xl" + borderWidth={1} + ></Box> + </Box> + )} + {colorList.map((color: string) => ( + <Box + m={1} + key={color} + onClick={() => clickCallback(color)} + justifyContent="space-between" + alignItems="center" + display="flex" + > + <Box bgColor={color} borderRadius="xl" height={6} width={6}></Box> + </Box> + ))} + </Flex> + </PopoverContent> </Portal> - </Menu> + </Popover> </Flex> ) } diff --git a/components/Tweaks/index.tsx b/components/Tweaks/index.tsx index 33f11ee..62252b0 100644 --- a/components/Tweaks/index.tsx +++ b/components/Tweaks/index.tsx @@ -96,7 +96,7 @@ export const Tweaks = (props: TweakProps) => { marginLeft={2} borderRadius="lg" paddingBottom={5} - zIndex="overlay" + zIndex={4} boxShadow="xl" maxH={'95vh'} fontSize="sm" diff --git a/components/config.ts b/components/config.ts index 0ae654e..ec1c691 100644 --- a/components/config.ts +++ b/components/config.ts @@ -60,7 +60,7 @@ export const initialVisuals = { nodeResolution: 12, labels: 2, labelScale: 1, - labelFontSize: 13, + labelFontSize: 10, labelLength: 40, labelWordWrap: 25, labelLineSpace: 1, @@ -88,7 +88,7 @@ export const initialVisuals = { linkHighlight: 'purple.500', backgroundColor: 'white', emacsNodeColor: 'gray.800', - labelTextColor: 'gray.900', + labelTextColor: 'black', labelBackgroundColor: '', labelBackgroundOpacity: 0.7, citeDashes: true, diff --git a/components/contextmenu.tsx b/components/contextmenu.tsx index 118b8bb..77deb48 100644 --- a/components/contextmenu.tsx +++ b/components/contextmenu.tsx @@ -45,10 +45,12 @@ import { import { OrgRoamGraphReponse, OrgRoamLink, OrgRoamNode } from '../api' import { deleteNodeInEmacs, openNodeInEmacs, createNodeInEmacs } from '../util/webSocketFunctions' import { BiNetworkChart } from 'react-icons/bi' +import { TagMenu } from './TagMenu' +import { initialFilter, TagColors } from './config' export default interface ContextMenuProps { background: Boolean - target: OrgRoamNode | null + target: OrgRoamNode | string | null nodeType?: string coordinates: { [direction: string]: number | undefined } handleLocal: (node: OrgRoamNode, add: string) => void @@ -56,6 +58,10 @@ export default interface ContextMenuProps { scope: { nodeIds: string[] } webSocket: any setPreviewNode: any + setTagColors: any + tagColors: TagColors + setFilter: any + filter: typeof initialFilter } export const ContextMenu = (props: ContextMenuProps) => { @@ -69,6 +75,10 @@ export const ContextMenu = (props: ContextMenuProps) => { scope, webSocket, setPreviewNode, + setTagColors, + tagColors, + setFilter, + filter, } = props const { isOpen, onOpen, onClose } = useDisclosure() const copyRef = useRef<any>() @@ -79,54 +89,59 @@ export const ContextMenu = (props: ContextMenuProps) => { zIndex="overlay" bgColor="white" color="black" - borderColor="gray.500" - maxWidth="xs" + //borderColor="gray.500" position="absolute" left={coordinates.left} top={coordinates.top} right={coordinates.right} bottom={coordinates.bottom} fontSize="xs" + boxShadow="xl" > - {target && ( + {typeof target !== 'string' ? ( <> - <Heading size="xs" isTruncated px={3} py={1}> - {target.title} - </Heading> - <MenuDivider borderColor="gray.500" /> - </> - )} - {scope.nodeIds.length !== 0 && ( - <> - <MenuItem onClick={() => handleLocal(target!, 'add')} icon={<PlusSquareIcon />}> - Expand local graph at node - </MenuItem> - <MenuItem onClick={() => handleLocal(target!, 'replace')} icon={<BiNetworkChart />}> - Open local graph for this node - </MenuItem> - </> - )} - {!target?.properties?.FILELESS ? ( - <MenuItem - icon={<EditIcon />} - onClick={() => openNodeInEmacs(target as OrgRoamNode, webSocket)} - > - Open in Emacs - </MenuItem> - ) : ( - <MenuItem icon={<AddIcon />} onClick={() => createNodeInEmacs(target, webSocket)}> - Create node - </MenuItem> - )} - {target?.properties?.ROAM_REFS && ( - <MenuItem icon={<ExternalLinkIcon />}>Open in Zotero</MenuItem> - )} - {scope.nodeIds.length === 0 && ( - <MenuItem icon={<BiNetworkChart />} onClick={() => handleLocal(target!, 'replace')}> - Open local graph - </MenuItem> - )} - {/* Doesn't work at the moment + {target && ( + <> + <Heading size="xs" isTruncated px={3} py={1}> + {target.title} + </Heading> + <MenuDivider borderColor="gray.500" /> + </> + )} + {scope.nodeIds.length !== 0 && ( + <> + <MenuItem onClick={() => handleLocal(target!, 'add')} icon={<PlusSquareIcon />}> + Expand local graph at node + </MenuItem> + <MenuItem + onClick={() => handleLocal(target!, 'replace')} + icon={<BiNetworkChart />} + > + Open local graph for this node + </MenuItem> + </> + )} + {!target?.properties?.FILELESS ? ( + <MenuItem + icon={<EditIcon />} + onClick={() => openNodeInEmacs(target as OrgRoamNode, webSocket)} + > + Open in Emacs + </MenuItem> + ) : ( + <MenuItem icon={<AddIcon />} onClick={() => createNodeInEmacs(target, webSocket)}> + Create node + </MenuItem> + )} + {target?.properties?.ROAM_REFS && ( + <MenuItem icon={<ExternalLinkIcon />}>Open in Zotero</MenuItem> + )} + {scope.nodeIds.length === 0 && ( + <MenuItem icon={<BiNetworkChart />} onClick={() => handleLocal(target!, 'replace')}> + Open local graph + </MenuItem> + )} + {/* Doesn't work at the moment <MenuItem closeOnSelect={false} closeOnBlur={false}> <Box _hover={{ bg: 'gray.200' }} width="100%"> <Popover @@ -156,71 +171,77 @@ export const ContextMenu = (props: ContextMenuProps) => { </Box> </MenuItem> */} - <MenuItem - icon={<ViewIcon />} - onClick={() => { - setPreviewNode(target) - }} - > - Preview - </MenuItem> - {target?.level === 0 && ( - <MenuItem - closeOnSelect={false} - icon={<DeleteIcon color="red.500" />} - color="red.500" - onClick={onOpen} - > - Permenantly delete note - </MenuItem> + <MenuItem + icon={<ViewIcon />} + onClick={() => { + setPreviewNode(target) + }} + > + Preview + </MenuItem> + {target?.level === 0 && ( + <MenuItem + closeOnSelect={false} + icon={<DeleteIcon color="red.500" />} + color="red.500" + onClick={onOpen} + > + Permenantly delete note + </MenuItem> + )} + </> + ) : ( + <TagMenu {...{ target, tagColors, filter, setTagColors, setFilter }} /> )} </MenuList> </Menu> - <Modal isCentered isOpen={isOpen} onClose={onClose}> - <ModalOverlay /> - <ModalContent zIndex="popover"> - <ModalHeader>Delete node?</ModalHeader> - <ModalCloseButton /> - <ModalBody> - <VStack spacing={4} display="flex" alignItems="flex-start"> - <Text>This will permanently delete your note:</Text> - <Text fontWeight="bold">{target?.title}</Text> - {target?.level !== 0 && ( - <Text> - This will only delete the from this heading until but not including the next node. - Your parent file and all other nodes will not be deleted. - </Text> - )} - <Text>Are you sure you want to do continue?</Text> - </VStack> - </ModalBody> - <ModalFooter> - <Button - mr={3} - onClick={() => { - console.log('closing') - onClose() - menuClose() - }} - > - Cancel - </Button> - <Button - variant="link" - colorScheme="red" - ml={3} - onClick={() => { - console.log('aaaaa') - deleteNodeInEmacs(target!, webSocket) - onClose() - menuClose() - }} - > - Delete node - </Button> - </ModalFooter> - </ModalContent> - </Modal> + {typeof target !== 'string' && ( + <Modal isCentered isOpen={isOpen} onClose={onClose}> + <ModalOverlay /> + <ModalContent zIndex="popover"> + <ModalHeader>Delete node?</ModalHeader> + <ModalCloseButton /> + <ModalBody> + <VStack spacing={4} display="flex" alignItems="flex-start"> + <Text>This will permanently delete your note:</Text> + <Text fontWeight="bold">{target?.title}</Text> + {target?.level !== 0 && ( + <Text> + This will only delete the from this heading until but not including the next + node. Your parent file and all other nodes will not be deleted. + </Text> + )} + <Text>Are you sure you want to do continue?</Text> + </VStack> + </ModalBody> + <ModalFooter> + <Button + mr={3} + onClick={() => { + console.log('closing') + onClose() + menuClose() + }} + > + Cancel + </Button> + <Button + variant="link" + colorScheme="red" + ml={3} + onClick={() => { + console.log('aaaaa') + deleteNodeInEmacs(target!, webSocket) + onClose() + menuClose() + }} + > + Delete node + </Button> + </ModalFooter> + </ModalContent> + </Modal> + )} </> ) } |