onHover effect on ReactMapGL not scaling properly - html

Currently I'm trying to replicate this hover effect of this website on my map component: http://www.francoisrisoud.com/projects where basically when you hover over a dot, it brings up a full screen image and when you click on it, it'll take you to a particular page. Currently this is my React and CSS code:
export default function Map({posts}) {
const [viewport, setViewport] = useState({
latitude: 36.592206968562685,
longitude: 3.332469343750031,
width:"100%",
height:"100vh",
zoom: 1.3,
});
const [selectedProperty, setSelectedProperty] = useState(null)
return (
<div>
<ReactMapGL {...viewport} mapboxApiAccessToken="//myAPIkey"
mapStyle="mapbox://styles/jay/cks5xkaa892cp17o5hyxcuu0z"
onViewportChange={viewport => {
setViewport(viewport);
}}>
{
posts &&
posts.map((maps) => (
<Marker key={maps.id} latitude={maps.Latitude} longitude={maps.Longitude}>
{/* <div>{maps.Title}</div> */}
<button className="marker-btn" onClick={e => {
e.preventDefault();
setSelectedProperty(maps);
}}>
<img src="placeholder.svg"/>
</button>
</Marker>
))}
{selectedProperty ? (
<Popup latitude={selectedProperty.Latitude} longitude={selectedProperty.Longitude}
onClose={() => {setSelectedProperty(null);}}>
<h1>{selectedProperty.Title}</h1>
</Popup>) : null}
</ReactMapGL>
</div>
);
}
CSS:
.marker-btn{
background: none;
border: none;
cursor: pointer;
}
.marker-btn :hover{
background: #000;
width: 100vw;
height: 100vh;
border: none;
cursor: pointer;
}
.marker-btn img{
width: 20px;
height: 20px;
}
But when I hover over the Marker in my map this is the result I get:
I want it so that it covers my whole map and not just start from the point where I'm hovering. Additionally, if I hover out of it I want it to go away but when I drag my cursor towards the big popup, it doesnt go away.

There are a lot of ways to do it. Here is mine:
Replace onClick prop and hover pseudo-class for the button inside the Marker component with onMouseEnter prop.
Create your own Popup that has a full height and width of the parent component.
Hide the Map component (by setting the width and height of viewport into 0%) and show the custom Popup component when the mouse enters the button and vice versa.
Here is the working code https://codesandbox.io/s/full-popup-mapbox-stackoverflow-36oi0?file=/src/App.js
Note: you have to attach your own Mapbox Token. You can get it from here https://account.mapbox.com/access-tokens/
import React, { useState } from "react";
import ReactMapGL, { Marker } from "react-map-gl";
import "./styles.css";
export default function App() {
const [viewport, setViewport] = useState({
latitude: 50.826758,
longitude: 4.380197,
width: "100vw",
height: "100vh",
zoom: 3
});
const YOURMAPBOXTOKEN = "";
const posts = [
{
id: 1,
latitude: 50.826758,
longitude: 4.380197
},
{
id: 2,
latitude: 48.893615,
longitude: 2.490906
},
{
id: 3,
latitude: 51.454007,
longitude: -0.235523
}
];
const [selectedProperty, setSelectedProperty] = useState(null);
const [isPopupShown, setIsPopupShown] = useState(false);
return (
<div className="root">
{!isPopupShown && (
<div className="map">
<ReactMapGL
{...viewport}
mapboxApiAccessToken={YOURMAPBOXTOKEN}
mapStyle="mapbox://styles/mapbox/dark-v9"
onViewportChange={(viewport) => {
setViewport(viewport);
}}
>
{posts &&
posts.map((item) => (
<Marker
key={item.id}
latitude={item.latitude}
longitude={item.longitude}
>
<button
className="marker-btn"
onMouseEnter={() => {
setSelectedProperty(item);
setViewport({
latitude: 50.826758,
longitude: 4.380197,
width: "0vw",
height: "0vh",
zoom: 3
});
setIsPopupShown(true);
}}
>
<img src="placeholder.svg" />
</button>
</Marker>
))}
</ReactMapGL>
</div>
)}
{/* SHOW FULL CUSTOM POPUP HERE */}
{selectedProperty && isPopupShown && (
<div className="full-popup">
// todo: create a closing popup button here
</div>
)}
</div>
);
}
Todo: you have to create a closing popup button for the custom Popup.
You can do it by reversing my code like this:
Set selectedProperty into null.
Set isPopupShown into false.
Sett the width and height of the viewport into 100%.

Related

How to deal with CSS overflow?

I have an overflow menu. It is very long, but has the following style:
height: 15rem;
overflow-y: auto;
Nevertheless when I click on the menu the browser window height becomes bigger as if the menu is opened in is full size (see the difference between browser scrollbar in the first and second pictures. Besides I have empty space below my page reserved for the full-size menu.
So the invisible part of the menu nevertheless takes space. How could I fix that?
Code:
<DataTable>
<TableContainer>
<TableToolbar>
<TableToolbarContent>
<TableToolbarSearch/>
<TableToolbarMenu>
<div style={ {display: displayMenu ? "block" : "none", height: "7.5rem", width: "230px", overflowY: "auto"}}>
{filterItems.map(e => { return (
<TableToolbarAction // onClick={ ()=> setItemClicked({...e, defaultChecked: false})} onChange = {() => { setDisplayMenu(true); if(headers.map(el => el.key).includes(e.key)) { setHeaders(headers.filter(el => el.key !== e.key)); } else { setHeaders([ ...headers, { key: e.key, header:
e.header } ]) } }} hasDivider = {true} >
<Checkbox defaultChecked={ true} id={ e.key} labelText={ e.header}/>
</TableToolbarAction>
) })}
</div>
</TableToolbarMenu>
</TableToolbarContent>
</TableToolbar>
</DataTable>
Use overflow: scroll; to give a scrollbar or use overflow: hidden; to hide the overflow.

Modify default classes of DataGrid material UI

In "DataGrid" material UI I am trying to modify the css properties like font weight, overflow of header.
Here is my jsx code
import React, {useState, useEffect} from 'react';
import {DataGrid, GridToolbarContainer, GridToolbarExport} from '#material- ui/data-grid';
import {makeStyles} from '#material-ui/styles';
const useStyles = makeStyles({
root: {
'& .super-app-theme--header': {
backgroundColor: 'white'
}
},
'.MuiDataGrid-root .MuiDataGrid-columnHeaderTitle': {
fontWeight: 'bold',
overFlow: 'visible'
}
});
function CustomToolbar() {
return (
<GridToolbarContainer>
<GridToolbarExport />
</GridToolbarContainer>
);
}
export default function DataTable(props) {
const classes = useStyles();
return (
<div style={{height: '700px', width: '100%'}} className={classes.root}>
<DataGrid
rows={props.records}
columns={props.headers}
pageSize={12}
components={{
Toolbar: CustomToolbar
}}
/>
</div>
);
}
I also tried to add properties like font weight and overflow in super-app-theme--header but it didn't work. Some properties like background colour are working but the properties which are already there in MuiDataGrid-columnHeaderTitle are not getting overridden.
I created a css file and in that overridden the properties with same class name and imported that css file
Here is the css code
.MuiDataGrid-columnHeaderTitle { font-weight: bold !important; overflow: visible !important; }
Using MUI V5+ and building on Pravin's answer you can define the header style this way:
<Datagrid
sx={{
'.MuiDataGrid-columnHeaderTitle': {
fontWeight: 'bold !important',
overflow: 'visible !important'
}
}}
/>

Blurring the contents in a div when Modal is displayed?

I have an side-drawer/modal that will slide into view when clicking on an image of my application. I'm trying to blur all the contents behind the side-drawer when it comes into view, I realized I might need another component like Backdrop that takes the whole content of the page and somehow blur the whole div when the side-drawer is displayed.
I tried using backdrop-filter but that's not supported in Chrome yet. Are there any alternatives? Or am I going to need a transparent "dummy" image to blur?
My component is just this:
import React from 'react';
import styles from './styles.module.css';
const backdrop = props => (
<div className={styles.backdrop} onClick={props.click}></div>
)
export default backdrop;
I tried this:
.backdrop {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
filter: blur(2px);
z-index: 300;
}
And mounting it on my app as so:
class App extends Component {
componentDidMount() {
const { loadUserAction } = this.props;
const {
auth: { token }
} = readLocalStorage();
if (token) loadUserAction(token);
}
render() {
return (
<BrowserRouter>
<Route exact path={signInPath} component={Login} />
<Backdrop />
<SideDrawer />
<ProtectedRoute exact path={feedPath} component={MovieFeed} />
</BrowserRouter>
);
}
}

Styling the placeholder in a TextField

The TextField API doesn't mention anything about how one could style the pseudo placeholder element of the input element.
Basically, I would like to change the default styling of the placeholder text, and the normal bag of tricks doesn't work, as I cannot access the element.
Is there a way I can get to it? And if so, what is the JSS/React/DOM equivalent way of writing ::-webkit-input-placeholder?
Case 1
Put the desired placeholder text in the label property of the TextField component, and use the labelClassName property of the TextField to customize it. You could also pass InputLabelProps with a className, classes or style attribute.
Case 2
Refrain from using the label property of TextField and put the placeholder text on its placeholder property instead. Leverage InputProps to override the generated HTML input element's class.
Code
The code below covers both aforementioned cases. CodeSandbox snippet.
import React from 'react';
import TextField from 'material-ui/TextField';
import { withStyles } from 'material-ui/styles';
import withRoot from '../components/withRoot';
const styles = {
'input-label': {
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
width: '100%',
color: 'red'
},
'input': {
'&::placeholder': {
textOverflow: 'ellipsis !important',
color: 'blue'
}
}
};
class Index extends React.Component {
render() {
return <div style={ {width: 150, margin: '0 auto'} }>
{/* Uses "label" and "labelClassName". */}
<TextField
fullWidth
label='I am a really really long red TextField label'
labelClassName={ this.props.classes['input-label'] } />
{/* Uses "label" and "InputLabelProps" with inline styles. */}
<TextField
fullWidth
label='I am a really really long green TextField label'
InputLabelProps={{
style: {
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
width: '100%',
color: 'green'
} }} />
{/* Uses "placeholder" and "InputProps" with "classes". */}
<TextField
fullWidth
margin='normal'
placeholder='I am a really really long glue TextField label'
InputProps={{ classes: {input: this.props.classes['input']} }} />
</div>;
}
}
export default withStyles(styles)(Index);
EDIT
The previous solutions are good if you'd like to personalize a specific component instance. To change the placeholder globally, see ninjaPixel's answer.
You can style the input at the top-level of your app, which will save you from having to create a custom input component with your styles applied to it (as suggested in other answers).
import { ThemeProvider } from "#material-ui/styles";
import { createMuiTheme } from "#material-ui/core/styles";
const customTheme = createMuiTheme({
overrides: {
MuiInput: {
input: {
"&::placeholder": {
color: "gray"
},
color: "white", // if you also want to change the color of the input, this is the prop you'd use
}
}
});
// Render it like this
<ThemeProvider theme={customTheme}>
<App />
</ThemeProvider>
You can use the following code to apply the placeholder style.
const styles = (theme: any) => createStyles({
input: {
'&::placeholder': {
fontStyle: 'italic',
},
},
});
<TextField
margin="normal"
variant="outlined"
placeholder="Filter..."
InputProps={{
classes: { input: classes.input}
}}
/>
Use InputLabelProps on TextField
<TextField
InputLabelProps={{
style: { color: '#fff', some other Styles },
}}
/>
I haven't found a proper answer to how I can access the inner input element, but as to how one could target the placeholder element using JSS, I found the answer in the source of the Input element, of which TextField is composed.
Basically, it's using the straight css names, just enclosed in quotes:
'&::-webkit-input-placeholder': { color: 'blue' }
you can add styling to your input using ::placeholder selector in css it'll work
::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: pink;
}
::-moz-placeholder { /* Firefox 19+ */
color: pink;
}
:-ms-input-placeholder { /* IE 10+ */
color: pink;
}
:-moz-placeholder { /* Firefox 18- */
color: pink;
}
To style only the placeholder without the label on top when focused - do the following:
const useStyles = makeStyles(theme => ({
label: {
color: 'rgba(0, 0, 0, 0.26)'
}
}));
const LoginForm = () => {
const classes = useStyles();
return (
<TextField
...
InputLabelProps={{
classes: {
root: classes.label,
}
}}
/>
)
}
Whether you are using the outlined, filled, or standard variants, the placeholder you might be referring to is actually the label and not the ::placeholder.
You can use sx in newest MUI versions.
<TextField
label="Username"
variant="standard"
sx={{ input: { color: "yellow" }, "label": {color: "blue"} }}
/>
With styled components I just use:
const StyledTextField = styled(TextField)`
label {
font-style: italic;
}
`;

Make Material-UI Reactjs FloatingActionButton float

After trying to find an example where the FloatingActionButton floats at its standard bottom-right screen position with no results, I come to you if you could provide one because it seems to be a normal button without floating to that corner by default.
Am I supposed to make it float by setting custom CSS rules?
Material-UI docs doesn't mention any property about floating Material-UI FloatingActionButton documentation.
Indeed, no property for this in the component FloatingActionButton for the moment.
Waiting for it :
1) A solution using inline styles :
At the top of your component, add :
const style = {
margin: 0,
top: 'auto',
right: 20,
bottom: 20,
left: 'auto',
position: 'fixed',
};
... and in your render method :
render() {
return <FloatingActionButton style={style}><ContentAdd /></FloatingActionButton>
}
OR
2) A solution using CSS file
Add in your CSS file (ex : styles.css referenced on your index.html) :
.fab {
margin: 0px;
top: auto;
right: 20px;
bottom: 20px;
left: auto;
position: fixed;
};
... and put on your React component :
render() {
return <FloatingActionButton className="fab"><ContentAdd /></FloatingActionButton>
}
I actually found this on the Material-UI documentation. I just made a few tweaks to it. Here's the resulting code.
import { makeStyles } from '#material-ui/core/styles';
import Fab from '#material-ui/core/Fab';
import AddIcon from '#material-ui/icons/Add';
const useStyles = makeStyles(theme => ({
fab: {
position: 'fixed',
bottom: theme.spacing(2),
right: theme.spacing(2),
},
}));
add this to your component
const classes = useStyles();
return (
<Fab color="primary" aria-label="add" className={classes.fab}>
<AddIcon />
</Fab>
);
If you want to manipulate CSS in material-ui, its better to use withStyles currying function.
Like this:
import React, {Component} from 'react';
import {Button} from "material-ui";
import {Add} from 'material-ui-icons';
import { withStyles } from 'material-ui/styles';
const style = theme => ({
fab: {
margin: 0,
top: 'auto',
left: 20,
bottom: 20,
right: 'auto',
position: 'fixed',
}
});
class MyPage extends Component{
render() {
const {classes} = this.props;
return <Button fab variant="fab" color="primary" aria-label="add" className={classes.fab}><Add />
</Button>
}
export default withStyles(style)(MyPage);
Documentation link: https://material-ui.com/customization/css-in-js/
In MUI v5, you can add the one-off styles directly to the Fab component via the sx props. Set the position to fixed (as opposed to absolute in other answers*) along with the anchor positions and you're done.
return (
<Fab
sx={{
position: "fixed",
bottom: (theme) => theme.spacing(2),
right: (theme) => theme.spacing(2)
}}
color="primary"
>
<AddIcon />
</Fab>
);
*: Setting to absolute will anchor the button to the bottom right of the closest relative container, the container itself will be moved if the user scrolls down which in turn moves the button. Use fixed value to anchor the button in relative to the viewport, so the scrolling would not affect the button position.
If you are creating a custom theme you can use the theme overrides to style the FAB (Floating Action Button) is floating in the bottom right corner:
import { createMuiTheme } from "#material-ui/core";
export default createMuiTheme({
overrides: {
MuiFab: {
root: {
position: 'absolute',
bottom: '2rem',
right: '2rem'
}
}
}
});
This will override the FAB for every component usage. You can use the same style with a specific class name and override it again for other usages.
In case of custom theme, in MUI v5 the overriding of the style it's a bit different from the v4,
see MUI v5-style-changes.
components: {
MuiFab: {
styleOverrides: {
root: {
position: 'fixed',
bottom: '2rem',
right: '2rem'
}
}
}
}