I'm trying to make ListItems inside a List draggable without changing too much structure, it seems to work but the styling is very off:
The icons and its names should be on one line but for some reason the <ListItemText> keeps being shoved into the next line when it shouldn't be. Here's my draggable code:
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="droppable" direction="vertical">
{(provided) => (
<div
ref={provided.innerRef}
{...provided.droppableProps}
>
{menuList.map((text, index) => (
<Draggable key={text} draggableId={text} index={index}>
{(provided) => (
<ListItem key={text} disablePadding}}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}>
<IconButton id={text} onClick={handleFav} disableRipple sx={{
minWidth: 0,
maxWidth: 1,
mr: 1,
justifyContent: 'center',
}}>
<StarRateRoundedIcon/>
</IconButton>
<IconButton sx={{ padding: 0, mr: 1 }}>
<VisibilityIcon sx={{ position: 'relative', verticalAlign: 'bottom', bottom: 1, color: '#00417d' }} />
</IconButton>
<ListItemText primary={text} sx={{ width: '16px', margin: 0 }} />
</ListItem>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
I did something similar for table cells and the items were inline, but this one isn't. I've tried setting the ListItem iteself to inline but that didn't seem to fix it. It seems that there's a div that either belongs to the draggable or the listitem itself that isn't the right size, but I can't tell which one:
The ListItemText component was causing it to wrap into its own line. I couldn't find a way to stop the component itself so I decided to just ditch it for a normal typography component, it now looks like how I want:
If anyone knows how to achieve the same but with a normal ListItemText I'd also love to know. This is how I got around it with Typography for now:
<Typography display={'inline'}>{text}</Typography>
Related
I am trying to use the re-resizable resizable to change the size of the popover but it is not working, is it impossible? and if so is there another way to resize the popover?
return (
<Resizable>
<Popover
open={!isStoredTabsNull()}
onClose={handleClose}
anchorEl={anchorEl}>
<Paper
style={{
backgroundColor: DefaultStyle.backgroundColor,
overflow: 'auto'}}>
{ storedTabs?.map((tabsGroup) => (
<StoredTabsItem
key={tabsGroup.id}
storedTabsGroup={tabsGroup}
projectFolder={projectFolder}
openFiles={openFiles}
overwriteState={overwriteState}
tabs={tabs}
/>
))}
</Paper>
</Popover>
</Resizable>
)
TL;DR
In a nutshell, wrap your Popover content (children) in <Resizable>, and not the Popover itself, to make it re-size.
Explanation
Yes, it is possible to resize an MUI Popover with re-resizable. Like the underlying Modal component, Popover's sizing is driven, by default, by its content. Adding a child[ren] wrapped in Resizable will give you the ability to resize the Popover. For example:
<Popover
open={!isStoredTabsNull()}
onClose={handleClose}
anchorEl={anchorEl}
anchorOrigin={{
vertical: "bottom",
horizontal: "left"
}}
>
<Paper
style={{
backgroundColor: DefaultStyle.backgroundColor,
overflow: "auto"
}}
>
<Resizable>
{storedTabs?.map((tabsGroup) => (
<StoredTabsItem
key={tabsGroup.id}
storedTabsGroup={tabsGroup}
projectFolder={projectFolder}
openFiles={openFiles}
overwriteState={overwriteState}
tabs={tabs}
/>
))}
</Resizable>
</Paper>
</Popover>
(In this example using your code, I added Resizable inside of Paper because Paper also gets its height from its content, unless otherwise defined.)
Which will result in:
Working CodeSandbox: https://codesandbox.io/s/mui-popover-with-re-resizeable-forked-t96dko?file=/demo.js
After some digging I found a different way. If anyone else is looking for a simpler answer that doesn't require to install another library you can use the CSS property resize (both meaning: "The element displays a mechanism for allowing the user to resize it, which may be resized both horizontally and vertically."(Source:developer.mozilla.org)
return (
<Popover
open={!isStoredTabsNull()}
onClose={handleClose}
anchorEl={anchorEl}>
<Paper
style={{
backgroundColor: DefaultStyle.backgroundColor,
overflow: 'auto',
resize: "both",
}}>
{ storedTabs?.map((tabsGroup) => (
<StoredTabsItem
key={tabsGroup.id}
storedTabsGroup={tabsGroup}
projectFolder={projectFolder}
openFiles={openFiles}
overwriteState={overwriteState}
tabs={tabs}
/>
))}
</Paper>
</Popover>
)
You can use "PaperProps" to give height and width like this. No need to use Resizeable.
<Popover
open={!isStoredTabsNull()}
onClose={handleClose}
anchorEl={anchorEl}
PaperProps={{
style: { width: 400, height: 400 },
}}
>
<Paper
style={{
backgroundColor: DefaultStyle.backgroundColor,
overflow: "auto",
}}
>
{storedTabs?.map((tabsGroup) => (
<StoredTabsItem
key={tabsGroup.id}
storedTabsGroup={tabsGroup}
projectFolder={projectFolder}
openFiles={openFiles}
overwriteState={overwriteState}
tabs={tabs}
/>
))}
</Paper>
</Popover>;
I am creating tabs using material ui and i want to add value beside label (ex: 05 written beside Recommendation label) which will be dynamic in the tabs component just like shown in below image:
Here is my code snippet of Tabs component:
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={value} onChange={handleChange} aria-label="basic tabs example">
<Tab label="Recommendation" />
<Tab label="Ongoing" />
<Tab label="Completed" />
</Tabs>
</Box>
One option is to create your own component, pass that in as a the Tab label, and then style it as needed. For example:
const TabWithCount = ({ children, count }) => {
return (
<Box sx={{ display: "inline-flex", alignItems: "center" }}>
<Typography component="div">{children}</Typography>
{count ? (
<Typography
component="div"
variant="body2"
sx={{ marginLeft: "0.5rem" }}
>
{count}
</Typography>
) : null}
</Box>
);
};
...
<Tab
label={<TabWithCount count="05">Recommendation</TabWithCount>}
/>
I've created a quick (unstyled) example to illustrate the solution: https://codesandbox.io/s/basictabs-material-demo-forked-i9543?file=/demo.js
Here I have defined the parent element display:"Grid" and with my child element have defined the gridColumnStart as below. It's working fine with the first element but not with the second child element. Below have attached my code.
return (
<Accordion
sx={{
display: "grid",
gridTemplateColumns: "1fr 2fr 1fr"
}}
>
<AccordionSummary
sx={{
gridColumnStart: "2",
gridColumnEnd: "4"
}}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<div>
<Typography variant="h1" sx={{ fontSize: "40px" }}>
{props.Title}
</Typography>
<Typography variant="subtitle1">{props.Description}</Typography>
<Button
size="small"
variant="outlined"
sx={{
width: "140px",
textAlign: "center",
marginTop: "10px",
color: "#2196F3",
borderColor: "#2196F3"
}}
>
More details
</Button>
</div>
</AccordionSummary>
<AccordionDetails
sx={{
gridColumnStart: "2",
gridColumnEnd: "3"
}}
>
{props.children}
</AccordionDetails>
</Accordion>
);
So here gridColumnStart and End working with AccordionSummary but not with AccordionDetails.
This is how it looks but I wanted the text to be in the middle. Not sure if the approach I'm heading towards is correct. Would appreciate if someone could help me.
This is a simplified Accordion definition:
<AccordionRoot>
<AccordionSummary />
<TransitionComponent>
<div>
<AccordionDetail />
</div>
</TransitionComponent>
</AccordionRoot>
The reason your AccordionDetail styles doesn't work is because it's applied to the children of the grid item instead of the grid item itself. To fix it, you need to set the grid properties directly in the child of the grid container which is TransitionComponent, if you inspect the element you can see the class name of the DOM elelment is MuiCollapse-root:
<Accordion
sx={{
display: "grid",
gridTemplateColumns: "1fr 2fr 1fr",
"& .MuiCollapse-root": {
gridColumnStart: "2",
gridColumnEnd: "3"
}
}}
>
I'm adding a chakra-ui menu dropdown button to a chart (from react-financial-charts, which is a library built over svg).
For some reason, when I click on the menu, there will be whitespace between the button and the dropdown menu. This only happens when I put the menu onto the chart. If I have the menu standalone in the browser, it'll work as expected.
This is the menu code:
function TestMenu() {
return (
<g className="react-financial-charts-enable-interaction">
<foreignObject
x={30}
y={30}
width={"100%"}
height={"100%"}
style={{ overflow: "auto" }}
>
<Menu>
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
Actions
</MenuButton>
<MenuList>
<MenuItem>Download</MenuItem>
<MenuItem>Create a Copy</MenuItem>
<MenuItem>Mark as Draft</MenuItem>
<MenuItem>Delete</MenuItem>
<MenuItem>Attend a Workshop</MenuItem>
</MenuList>
</Menu>
</foreignObject>
</g>
);
}
This is the full codesandbox:
https://codesandbox.io/s/nervous-haze-3mz2c?file=/src/BasicLineSeries.tsx:511-1199
EDIT
If I remove x={0} and y={0} from foreignObject and include style={{ marginTop: "30px", marginLeft: "30px" }} into MenuButton instead, as suggested by one of the answers, this will solve the problem only if the chart is at the top of the page. Otherwise, if there is a div before the chart, then this will occur:
and here's the full codesandbox for that:
https://codesandbox.io/s/nostalgic-pare-c5rxu?file=/src/BasicLineSeries.tsx
UPDATED
According to the menu list position problem, you can make use of Portal to move the entire list options to the bottom of the DOM so that its style will not be affected by any style/component inside the Chart.
...
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
transition="all 0.001s"
borderRadius="md"
borderWidth="0px"
_hover={{ bg: "gray.400" }}
_expanded={{ bg: "blue.400" }}
_focus={{ boxShadow: "none" }}
style={{ marginTop: "30px", marginLeft: "30px" }} // better move the style to css file
>
Actions
</MenuButton>
<Portal>
<MenuList zIndex={10}>
<MenuItem>Download</MenuItem>
<MenuItem>Create a Copy</MenuItem>
<MenuItem>Mark as Draft</MenuItem>
<MenuItem>Delete</MenuItem>
<MenuItem>Attend a Workshop</MenuItem>
</MenuList>
</Portal>
</Menu>
...
The Updated Codesandbox
The white space is triggered by the foreignObject's x and y where the MenuList is respecting the space specified in foreignObject. (You can try to increase x and y, you will see a larger gap between the button and menu list)
To solve the problem, you can remove the x and y and apply the margin on MenuButton
...
<foreignObject
width={"100%"}
height={"100%"}
style={{ overflow: "auto" }}
>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
transition="all 0.001s"
borderRadius="md"
borderWidth="0px"
_hover={{ bg: "gray.400" }}
_expanded={{ bg: "blue.400" }}
_focus={{ boxShadow: "none" }}
style={{ marginTop: "30px", marginLeft: "30px" }} // better move the style to css file
>
Actions
</MenuButton>
<MenuList>
<MenuItem>Download</MenuItem>
<MenuItem>Create a Copy</MenuItem>
<MenuItem>Mark as Draft</MenuItem>
<MenuItem>Delete</MenuItem>
<MenuItem>Attend a Workshop</MenuItem>
</MenuList>
</Menu>
</foreignObject>
...
Here is the modified codesandbox
I am currently using react-infinite-scroll-component to paginate the comments from a certain post. There is a button in the comment section which shows a drawer that is supposed to show the paginated comments. The problem is, the react-infinite-scroll-component doesn't work, as it does not fire
the "next" function.
Here is the code:
<div>
<Drawer
anchor={"bottom"}
open={open}
onClose={handleDrawer}
style={{ height: "100vh", overflow: "auto", margin: "0px 4px" }}
>
<Toolbar>
<Typography variant="h4" style={{ flexGrow: 1 }}>
Comments
</Typography>
<IconButton onClick={handleDrawer}>
<CloseIcon />
</IconButton>
</Toolbar>
<Divider />
<br />
<CommentForm
comment={comment}
handleChange={handleChange}
handleSubmit={handleSubmit}
/>
<InfiniteScroll
dataLength={page}
next={More}
hasMore={hasMore}
loader={
<>
<br />
<CircularProgress />
</>
}
style={{
overflow: "hidden",
}}
scrollThreshold={1}
>
<CommentList comments={comments} id={session.id} />
</InfiniteScroll>
</Drawer>
</div>
The drawer is mostly similar to Youtube's comment drawer on the mobile app. Is there anything I am missing here?
Probably, the problem is the relation with Drawer and Infinite Scroll height. The height of Infinite Scroll is not reaching the right point to trigger next function. If you provide the demo in Codesandbox would be easier to understand.
Fixed height of infinite scroll container
<Box sx={{ height: 500 }}>
<InfiniteScroll
dataLength={page}
next={More}
hasMore={hasMore}
loader={
<>
<br />
<CircularProgress />
</>
}
style={{
overflow: "hidden",
}}
scrollThreshold={1}
>
<CommentList comments={comments} id={session.id} />
</InfiniteScroll>
</Box>