I want to implement panel where items are placed using the following layout:
I tried the following code:
import React, { useCallback, useEffect } from "react";
import { Box, Grid, Tab, Tabs, Typography } from "#material-ui/core";
import { makeStyles, Theme } from "#material-ui/core/styles";
import { sizing } from "#material-ui/system";
const useStyles1 = makeStyles((theme: Theme) => ({
color: {
backgroundColor: "green",
border: "1px solid black"
}
}));
const useStyles2 = makeStyles((theme: Theme) => ({
color: {
backgroundColor: "mediumvioletred",
border: "1px solid black"
}
}));
const useStyles3 = makeStyles((theme: Theme) => ({
color: {
backgroundColor: "orange",
border: "1px solid black"
}
}));
export default function Hello() {
const classes1 = useStyles1();
const classes2 = useStyles2();
const classes3 = useStyles3();
return (
<>
<Grid
spacing={0}
container
direction="row"
justifyContent="flex-start"
xs={12}
alignItems={"stretch"}
style={{ height: "100vh", overflow: "auto", flexGrow: 1 }}
>
<Grid
// spacing={0}
// container
// direction="row"
// xs={3}
// style={{ height: "100%", overflow: "auto" }}
>
<Grid item xs={12}>
<Grid
className={classes1.color}
container
direction="column"
justifyContent="flex-start"
alignItems="center"
>
<Grid item xs={12}>
<Box m={2}>item link 1</Box>
</Grid>
<Grid item xs={12}>
<Box m={2}>item link 2</Box>
</Grid>
<Grid item xs={12}>
<Box m={2}>item link 3</Box>
</Grid>
<Grid item xs={12}>
<Box m={2}>item link 4</Box>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid
spacing={0}
container
direction="row"
xs={2}
className={classes2.color}
style={{ height: "100%", overflow: "auto" }}
>
<Grid item xs={12}>
<Box m={10}>item 11</Box>
</Grid>
<Grid item xs={12}>
<Box m={10}>item 11</Box>
</Grid>
<Grid item xs={12}>
<Box m={10}>item 13</Box>
</Grid>
<Grid item xs={12}>
<Box m={10}>item 14</Box>
</Grid>
<Grid item xs={12}>
<Box m={10}>item 15</Box>
</Grid>
<Grid item xs={12}>
<Box m={10}>item 16</Box>
</Grid>
</Grid>
<Grid
container
direction="row"
xs={4}
alignItems={"stretch"}
style={{ height: "100%", overflow: "auto" }}
>
<Grid item xs={12}>
<Grid
className={classes3.color}
container
direction="row"
justifyContent="space-around"
alignItems="center"
style={{ width: "100%", overflow: "auto" }}
>
<Grid item xs={12}>
<Box m={2}>item area 1</Box>
</Grid>
<Grid item xs={12}>
<Box m={2}>item area 2</Box>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
</>
);
}
Full code: https://stackblitz.com/edit/react-ts-k6hpuf?file=Hello.tsx
Do you know how I can implement drag for the borders and proper layout using typescript?
Here's a working example using Material UI and react-beautiful-dnd
Using drag and drop based on a ticket-based system like Jira
App.js
import React, { useState } from "react";
import makeStyles from "#material-ui/core/styles/makeStyles";
import Grid from "#material-ui/core/Grid";
import { DragDropContext } from "react-beautiful-dnd";
import Column from "./Column";
const App = () => {
function range(start, end) {
return Array(end - start + 1)
.fill()
.map((_, idx) => start + idx);
}
const initialColumns = {
links: {
id: "links",
list: [
{ id: "1", text: "text1" },
{ id: "2", text: "text2" },
{ id: "3", text: "text3" }
]
},
items: {
id: "items",
list: []
},
area1: {
id: "area1",
list: []
},
area2: {
id: "area2",
list: [
{ id: "7", text: "text7" },
{ id: "8", text: "text8" },
{ id: "9", text: "text9" }
]
}
};
range(4, 25).forEach((idx) => {
initialColumns.area1.list.push({
id: idx.toString(),
text: "text" + idx.toString()
});
});
range(24, 60).forEach((idx) => {
initialColumns.items.list.push({
id: idx.toString(),
text: "text" + idx.toString()
});
});
const [columns, setColumns] = useState(initialColumns);
const onDragEnd = ({ source, destination }) => {
// Make sure we have a valid destination
if (destination === undefined || destination === null) return null;
// Make sure we're actually moving the item
if (
source.droppableId === destination.droppableId &&
destination.index === source.index
)
return null;
// Set start and end variables
const start = columns[source.droppableId];
const end = columns[destination.droppableId];
// If start is the same as end, we're in the same column
if (start === end) {
// Move the item within the list
// Start by making a new list without the dragged item
console.log(start);
const newList = start.list.filter((_, idx) => idx !== source.index);
// Then insert the item at the right location
newList.splice(destination.index, 0, start.list[source.index]);
// Then create a new copy of the column object
const newCol = {
id: start.id,
list: newList
};
// Update the state
setColumns((state) => ({ ...state, [newCol.id]: newCol }));
return null;
} else {
// If start is different from end, we need to update multiple columns
// Filter the start list like before
const newStartList = start.list.filter((_, idx) => idx !== source.index);
// Create a new start column
const newStartCol = {
id: start.id,
list: newStartList
};
// Make a new end list array
const newEndList = end.list;
// Insert the item into the end list
newEndList.splice(destination.index, 0, start.list[source.index]);
// Create a new end column
const newEndCol = {
id: end.id,
list: newEndList
};
// Update the state
setColumns((state) => ({
...state,
[newStartCol.id]: newStartCol,
[newEndCol.id]: newEndCol
}));
return null;
}
};
return (
<DragDropContext onDragEnd={onDragEnd}>
<Grid
container
direction="row"
justifyContent="space-around"
alignItems="stretch"
>
<Grid item xs={1}>
<Column
isLinks={true}
backgroundColor={"lightgreen"}
height={"90vh"}
width={"100%"}
column={columns.links}
key={columns.links.id}
/>
</Grid>
<Grid item xs={1}>
<Column
backgroundColor={"salmon"}
height={"90vh"}
width={"100%"}
column={columns.items}
key={columns.items.id}
/>
</Grid>
<Grid item xs={9}>
<Column
className={"flex-col-scroll"}
height={"42vh"}
width={"100%"}
backgroundColor={"darkorange"}
column={columns.area1}
key={columns.area1.id}
/>
<Column
className={"flex-col-scroll"}
height={"42vh"}
width={"100%"}
backgroundColor={"darkorange"}
column={columns.area2}
key={columns.area2.id}
/>
</Grid>
</Grid>
</DragDropContext>
);
};
export default App;
const useStyles = makeStyles((theme) => ({}));
Column.js
import React from "react";
import { Droppable } from "react-beautiful-dnd";
import RootRef from "#material-ui/core/RootRef";
import List from "#material-ui/core/List";
import ListItemCustom from "./ListItemCustom";
import Typography from "#material-ui/core/Typography";
const Column = ({ isLinks, height, width, backgroundColor, column }) => {
const linksStyle = !isLinks
? {
maxHeight: "85%",
overflow: "auto"
}
: {};
return (
<div
style={{
height: height,
width: width,
backgroundColor: backgroundColor,
margin: 10,
padding: 20,
color: "white"
}}
>
<Typography variant={"h4"}>{column.id}</Typography>
<Droppable droppableId={column.id}>
{(provided) => (
<RootRef rootRef={provided.innerRef}>
<List style={linksStyle}>
{column.list.map((itemObject, index) => {
return <ListItemCustom index={index} itemObject={itemObject} />;
})}
{provided.placeholder}
</List>
</RootRef>
)}
</Droppable>
</div>
);
};
export default Column;
ListItemCustom.js
import React from "react";
import ListItem from "#material-ui/core/ListItem";
import ListItemText from "#material-ui/core/ListItemText";
import ListItemSecondaryAction from "#material-ui/core/ListItemSecondaryAction";
import IconButton from "#material-ui/core/IconButton";
import { Draggable } from "react-beautiful-dnd";
const ListItemCustom = ({ itemObject, index }) => {
return (
<Draggable draggableId={itemObject.id} key={itemObject.id} index={index}>
{(provided) => (
<ListItem
key={itemObject.id}
role={undefined}
dense
button
ContainerComponent="li"
ContainerProps={{ ref: provided.innerRef }}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<ListItemText
sytles={{ fontFamily: "Quicksand" }}
primary={`${itemObject.text}`}
/>
<ListItemSecondaryAction>
<IconButton
edge="end"
aria-label="comments"
question-uid={itemObject.id}
>
{/* <DeleteIcon /> */}
</IconButton>
</ListItemSecondaryAction>
</ListItem>
)}
</Draggable>
);
};
export default ListItemCustom;
Update 1: added bad scrolling
Update 2: added scrolling and another vertical sidebar like in the architecture
Update 3: reordered layout spacing using material UI grid API
Update 4: added main Code in case code sandbox link breaks
Related
My site has a component (NavPanel) that consists of two components (a back button (BackToButton ) and a search field (SearchTextField )). With a standard screen size, they are positioned as they should be, but if the screen sizes are reduced, then these two components overlap each other.
The most optimal for me would be if, with a compressed screen size, the second component (SearchTextField ) will be located under the first (BackToButton ). Tell me how you can solve this problem?
const Style = {
paddingLeft: '8%',
paddingRight: '8%',
minHeight: '70px',
alignItems: 'center',
flexWrap: 'nowrap',
whiteSpace: 'nowrap'
}
export default function NavPanel() {
return (
<Grid container sx={Style}>
<BackToButton />
<SearchTextField />
</Grid>
);
}
Here you go...
You didn't use the grid correctly.
See the forked snippet here.
EDIT 1
A:
B:
EDIT 2
You can change the breakpoint from sm to md. It means that PageNameBackToButton and FilterButtonSearchTextField will be stacked earlier, but A will not happen.
See the forked snippet here.
PageNameBackToButton.jsx
import React from "react";
import { Tooltip } from "#mui/material";
import BackToButton from "./BackToButton";
const PageName = {
color: "#000000",
fontSize: "20px",
fontWeight: "700",
letterSpacing: "0.2px",
paddingRight: "20px"
};
const PageNameBackToButtonContainerStyle = {
width: "50%",
justifyContent: "start",
alignContent: "center"
};
export default function PageNameBackToButton(props) {
return (
<div sx={PageNameBackToButtonContainerStyle}>
<BackToButton />
<div style={{ marginTop: "5px", display: "inline-block" }}>
<span style={PageName}>Some Text</span>
<span>
<Tooltip title={`Here long long text`} placement="right">
<span
style={{ fontSize: "18px", color: "#ef1400", userSelect: "none" }}
>
Live
</span>
</Tooltip>
</span>
</div>
</div>
);
}
FilterButtonSearchTextField.jsx
import { TextField } from "#mui/material";
const FilterButtonSearchTextFieldContainerStyle = {};
const SearchTextField = {};
export default function FilterButtonSearchTextField() {
return (
<div sx={FilterButtonSearchTextFieldContainerStyle}>
<TextField
required
label="Search Search"
size="small"
style={SearchTextField}
/>
</div>
);
}
Filter.jsx
import React from "react";
import { Grid } from "#mui/material";
import FilterButtonSearchTextField from "./FilterButtonSearchTextField";
import PageNameBackToButton from "./PageNameBackToButton";
import { styled } from "#mui/material/styles";
const FilterContainerStyle = {};
const Root = styled("div")(({ theme }) => ({
padding: theme.spacing(1),
[theme.breakpoints.up("md")]: {
display: "flex",
justifyContent: "flex-end"
}
}));
export default function Filter(props) {
const pageName = props.pageName !== undefined ? props.pageName : "";
const showBackToButton =
props.showBackToButton !== undefined ? props.showBackToButton : false;
return (
<Grid container spacing={2} sx={FilterContainerStyle}>
<Grid item md={6} xs={12}>
<PageNameBackToButton
showBackToButton={showBackToButton}
pageName={pageName}
/>
</Grid>
<Grid item md={6} xs={12}>
<Root>
<FilterButtonSearchTextField table={props.table} />
</Root>
</Grid>
</Grid>
);
}
<Grid container> is meaningless without some <Grid item>s inside it.
Just like the Bootstrap,
The grid creates visual consistency between layouts while allowing flexibility across a wide variety of designs. Material Design's responsive UI is based on a 12-column grid layout.
Your code would be like this:
<Grid container spacing={1} sx={Style}>
<Grid item xs={12} sm={6}>
<BackToButton />
</Grid>
<Grid item xs={12} sm={6}>
<SearchTextField />
</Grid>
</Grid>
I strongly recommend reading the MUI Grid Docs.
I have here a CircularLoader using Material UI.
My only problem is that if the variant is indeterminate then show the loader as is with no percentage while if it is determinate show the percentage inside the loader and the text as is.
Codesandbox: CLICK HERE
const CircularLoader = (props) => {
const {
height = "auto",
color = "primary",
text = "",
value = 0,
variant = "indeterminate"
} = props;
return (
<Grid
component="div"
container
justifyContent="center"
alignItems="center"
flexDirection="column"
sx={{ height }}
>
<CircularProgress
// variant={variant}
// value={value}
disableShrink
color={color}
thickness={4}
sx={{ marginBottom: "0.5rem" }}
/>
<Typography variant="body1" component="div" color={color}>
{text}
</Typography>
</Grid>
);
};
export default CircularLoader;
I think it's probably best to split these components up (since they have different props). But if you want them in the same component, you need to provide a dynamic value from 0-100 to the determinate variant. See the docs source code example.
In your case you could have a ternary choose between which variant to render, as a quick demo the following should work (note i'm ignoring value prop and simulating it with progress for demo purposes):
import React from "react";
import Grid from "#mui/material/Grid";
import Stack from "#mui/material/Stack";
import Typography from "#mui/material/Typography";
import CircularProgress from "#mui/material/CircularProgress";
import Box from '#mui/material/Box';
const CircularLoader = ({
height = "auto",
color = "primary",
text = "",
value = 0,
variant = "indeterminate"
}) => {
const [progress, setProgress] = React.useState(0);
React.useEffect(() => {
const timer = setInterval(() => {
setProgress((prevProgress) =>
prevProgress >= 100 ? 0 : prevProgress + 10
);
}, 800);
return () => {
clearInterval(timer);
};
}, []);
return (
<Grid
component="div"
container
justifyContent="center"
alignItems="center"
flexDirection="column"
sx={{ height }}
>
{variant === "indeterminate" ? (
<CircularProgress />
) : (
<Stack spacing={2} direction="row">
<Box sx={{ position: 'relative', display: 'inline-flex' }}>
<CircularProgress variant="determinate" value={progress}/>
<Box
sx={{
top: 0,
left: 0,
bottom: 0,
right: 0,
position: 'absolute',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Typography variant="caption" component="div" color="text.secondary">
{`${Math.round(progress)}%`}
</Typography>
</Box>
</Box>
</Stack>
)}
<Typography variant="body1" component="div" color={color}>
{text}
</Typography>
</Grid>
);
};
export default CircularLoader;
progress is just simulated in this case for demo purposes, whereas you need to pass down progress as value via props and use that in the CircularProgress component (it should be some dynamic value linked to actual loading progress state).
Link to Sandbox
Created this accordion and will use it as a menu item.
However, when I click Main title, accordion summary moves vertically downward.
How can I keep Main tile fixed while opening?
sandbox
import React from "react";
import {
Typography,
Grid,
Accordion,
AccordionSummary,
AccordionDetails,
ListItem
} from "#material-ui/core";
import { createStyles, makeStyles, Theme } from "#material-ui/core/styles";
import ExpandMoreIcon from "#material-ui/icons/ExpandMore";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
panelSummary: {
flexDirection: "row-reverse",
paddingLeft: "0px"
},
heading: {
fontSize: theme.typography.pxToRem(15),
fontWeight: theme.typography.fontWeightRegular
},
innerMenuItem: {
paddingLeft: "32px"
},
expanded: {
padding: "0px"
}
})
);
export default function App() {
const classes = useStyles();
return (
<Accordion>
<AccordionSummary
className={classes.panelSummary}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography className={classes.heading}>Main title</Typography>
</AccordionSummary>
<AccordionDetails>
<Grid container direction="column">
<ListItem className={classes.innerMenuItem} button key={1}>
<Typography className={classes.heading}>Sub Item 1</Typography>
</ListItem>
<ListItem
className={classes.innerMenuItem}
button
key={2}>
<Typography className={classes.heading}>Sub Item 2</Typography>
</ListItem>
</Grid>
</AccordionDetails>
</Accordion>
);
}
You can just pass in disableGutters as true in version 5 of mui
<Accordion disableGutters>
// ....
</Accordion>
When expanded, the summary's vertical margin is set to some value, you need to reset it if you don't want to see the summary size changes during the expansion:
V5
<AccordionSummary
sx={{
"&.Mui-expanded": {
minHeight: 0
},
"& .MuiAccordionSummary-content.Mui-expanded": {
// margin from https://github.com/mui-org/material-ui/blob/cc0e2ab63e8be9ec4d51a49bfde17ef28fc77b9c/packages/mui-material/src/AccordionSummary/AccordionSummary.js#L64-L64
margin: "12px 0"
}
}}
>
V4
panelSummary: {
"&.Mui-expanded": {
minHeight: 0
},
"& .MuiAccordionSummary-content.Mui-expanded": {
margin: "auto"
}
},
I would like a scroll to the top button to sit at the bottom, much like a footer. Current Behavior: I have an array I'm filtering through and displaying different lengths of data. When there is only one item in a certain category the button will move all the way to the top of the page under the item. Wanted Behavior: I would like the button to stay at the bottom and not move, but not sticky. my button styling is as follows:
import React, { useState, useContext } from "react"
// components
import SelectStatus from "../components/SelectStatus"
import RepoCard from "../components/RepoCard"
// Context
import { GithubContext } from "../context/GithubContext"
// Material UI Stuff
import TextField from "#material-ui/core/TextField"
import CardContent from "#material-ui/core/CardContent"
import Button from "#material-ui/core/Button"
import Card from "#material-ui/core/Card"
import Grid from "#material-ui/core/Grid"
import { makeStyles } from "#material-ui/core/styles"
import Container from "#material-ui/core/Container"
// context
const useStyles = makeStyles((theme) => ({
cardGrid: {
paddingTop: theme.spacing(8),
paddingBottom: theme.spacing(8),
},
card: {
display: "flex",
marginBottom: 10,
minHeight: 90,
},
form: {
display: "flex",
alignItems: "center",
width: "100%",
},
content: {
display: "flex",
alignItems: "center",
width: "100%",
justifyContent: "space-between",
},
jobField: {
margin: 0,
padding: 0,
},
grid: {
padding: 0,
},
dashboardContainer: {
marginTop: 70,
padding: 10,
},
loading: {
textAlign: "center",
},
}))
const INITIAL_STATE = {
language: "All",
search: "",
}
const Profile = () => {
const [formData, setFormData] = useState(INITIAL_STATE)
const [updated, setUpdated] = useState(false)
const [created, setCreated] = useState(false)
const { data } = useContext(GithubContext)
const handleUpdated = () => {
setUpdated(!updated)
data &&
data.sort((a, b) => {
if (updated) return a.updated_at > b.updated_at ? -1 : 1
return a.updated_at > b.updated_at ? 1 : -1
})
}
const handleCreated = () => {
setCreated(!created)
data &&
data.sort((a, b) => {
if (created) return a.created_at > b.created_at ? -1 : 1
return a.created_at > b.created_at ? 1 : -1
})
}
const handleInputChange = (field) => (e) => {
setFormData({ ...formData, [field]: e.target.value })
}
const classes = useStyles()
return (
<>
<div style={{ marginTop: 85, marginBottom: 85 }}>
<Container className={classes.dashboardContainer}>
<Card className={classes.card} style={{ width: "100%" }}>
<CardContent className={classes.content}>
<div className={classes.form}>
<Grid
container
spacing={2}
alignItems='center'
justify='space-between'
>
<Grid item sm={4} xs={12} className={classes.grid}>
<SelectStatus
language={formData.language}
handleInputChange={handleInputChange}
/>
</Grid>
<Grid item sm={4} xs={12} className={classes.grid}>
<TextField
className={classes.jobField}
margin='normal'
fullWidth
id='search'
name='search'
label='Search by Title'
placeholder='Search by Title'
onChange={handleInputChange("search")}
value={formData.search}
/>
</Grid>
<Grid item sm={2} xs={12} className={classes.grid}>
<Button
fullWidth
variant='contained'
color='primary'
onClick={handleUpdated}
>
Updated {updated ? "(oldest)" : "(newest)"}
</Button>
</Grid>
<Grid item sm={2} xs={12} className={classes.grid}>
<Button
fullWidth
variant='contained'
color='primary'
onClick={handleCreated}
>
Created {created ? "(oldest)" : "(newest)"}
</Button>
</Grid>
</Grid>
</div>
</CardContent>
</Card>
</Container>
{!data ? (
<h1 className={classes.loading}>Initializing Repos...</h1>
) : (
<Container style={{ padding: 10 }}>
{!data ? (
<div style={{ placeItems: "center" }}>Loading...</div>
) : (
<Grid container alignItems='center' spacing={4}>
{data &&
data
.filter((data) => {
if (formData.language === "All") return true
return data.language === formData.language
})
.filter((data) => {
if (formData.search === "") return true
return (data.name + data.language)
.toLowerCase()
.includes(formData.search.toLowerCase())
})
.map((user) => <RepoCard key={user.id} user={user} />)}
</Grid>
)}
</Container>
)}
<Button
variant='contained'
color='primary'
disableElevation
style={{
borderRadius: 0,
display: "block",
marginLeft: "auto",
marginRight: "auto",
position: "relative",
marginTop: "80px"
}}
>
Back to Top
</Button>
</div>
</>
)
}
export default Profile
You can use flex and space-around feature. like below:
<div class="container">
<div>
your items
</div>
<Button
variant='contained'
color='primary'
disableElevation
style={{
borderRadius: 0,
elevation: "disabled",
display: "block",
marginLeft: "auto",
marginRight: "auto",
marginTop: "80px",
}}
>
Back to Top
</Button>
</div>
Style:
.container{
display: flex;
flex-direction:column;
justify-content: space-between;
}
Using this you split your content to two part.
First part which will be your array items will be shown at the top.
The second part which is your button will be shown at the bottom.
This is because your making a space between first part and second part by using space-around of justify-content.
without sticky or fixed the only thing i can think of is using position: absolute; and bottom: 0; or placing them in a container with some combination of the same, then positioning it as needed. same as Joeri in the comments, would need a bit more context to help :) good luck!
I'm working on a map with an image overlay that has adjustable opacity. Here is the component code:
import React from 'react'
import PropTypes from 'prop-types'
import { MapWithGroundOverlay } from './MapWithGroundOverlay'
import { withStyles } from '#material-ui/core/styles'
import Box from '#material-ui/core/Box'
import FormLabel from '#material-ui/core/FormLabel'
import Slider from '#material-ui/lab/Slider'
import Grid from '#material-ui/core/Grid'
import Paper from '#material-ui/core/Paper'
const styles = theme => ({
root: {
flexGrow: 1,
},
paper: {
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
},
label: {
padding: theme.spacing(3),
}
})
class AdjustableGroundoverlay extends React.PureComponent {
constructor(props, context) {
super(props, context)
this.state = {opacity: 0.5}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event, value) {
this.setState(state => ({
opacity: value
}));
}
render() {
return (
<Grid container className={this.props.classes.root} spacing={2}>
<Grid item xs={12}>
<MapWithGroundOverlay
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_API_KEY}&v=3.exp&libraries=geometry,drawing,places`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `600px` }} />}
mapElement={<div style={{ height: `100%` }} />}
opacity={this.state.opacity}
/>
</Grid>
<Grid item xs={6}>
<Paper className={this.props.classes.paper}>
<Box flexDirection="column">
<FormLabel className={this.props.classes.label}>Overlay opacity</FormLabel>
<Slider
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
</Box>
</Paper>
</Grid>
</Grid>
);
}
}
AdjustableGroundoverlay.propTypes = {
classes: PropTypes.object.isRequired,
}
export default withStyles(styles)(AdjustableGroundoverlay)
The problem is that the FormLabel and Slider are too close together. If I hover over them, I see that the Slider has a negative margin of -24px:
It seems like the content of the FormLabel therefore sits directly on top of it:
I've tried to change the styling of the Slider by adding these classes to the component in accordance with https://material-ui.com/api/slider/#css:
<Slider
classes={{container: {marginTop: -12}}}
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
but the spacing between the FormLabel and the Slider remains the same. Any idea what is wrong with this implementation?
Update
I've noticed in the console that there is this error:
I'm not sure why the key 'container' is not valid though since it is mentioned in https://material-ui.com/api/slider/#css.
I resolved this by putting the slider in a Box with mt set to 1:
<Paper className={this.props.classes.paper}>
<Box flexDirection="column">
<FormLabel className={this.props.classes.label}>Overlay opacity</FormLabel>
<Box mt={1}>
<Slider
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
</Box>
</Box>
</Paper>
Now there is more spacing between the label and the slider: