I am using react-monaco-editor but I am not able to make it responsive. It takes a fixed height and width in the components. If I change the screen size, the width stays fixed.
<MonacoEditor
width="1200"
height="600"
language="typescript"
theme="vs-dark"
defaultValue="//type your code here"
value={code}
options={options}
onChange={this.onChange}
editorDidMount={this.editorDidMount}
className='editor1'
/>
If I remove the width and height from the component, the component diminishes. I tried overriding the component className with flex. But it doesn't seem to work well.
.react-monaco-editor-container {
flex: 2;
}
Can you help me with the CSS to make this responsive?
Simply in options set automaticLayout: true
You could add a resize handler in order to figure out the available space for your editor container and pass it to your Monaco Editor right away.
There are as well different libraries that assist you with that:
https://www.npmjs.com/package/react-resize-detector
Here you can find a Sandbox example with using the library above:
https://codesandbox.io/s/vibrant-goldwasser-3d8j7?fontsize=14&hidenavigation=1&theme=dark
import React from "react";
import { withResizeDetector } from "react-resize-detector";
const Editor = ({ width, height }) => (
<div
style={{
background: "grey",
height: height,
width: width
}}
>
Editor container with {width} x {height}
</div>
);
export default withResizeDetector(Editor);
After a few things didn't work with CSS, I tried javascript to solve this
updateDimensions = () => {
this.setState({
width: window.innerWidth - 501,
height: window.innerHeight - 50,
});
};
componentDidMount() {
window.addEventListener("resize", this.updateDimensions);
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateDimensions);
}
Storing the height and width in the state and changing on resize event did the job.
Related
Here is a code sandbox example where I am trying to display a map inside of a specific component. But, I am not able to get the deck.gl and react-map-gl divs to live inside their parent. instead, they spill out to the extent of the document body.
The basic layout of the example is:
<Box id='mapcontainer'>
<DeckGL id="deck-gl">
<MapView id="map" >
<StaticMap/>
</MapView>
</DeckGL>
</Box>
It appears that Deck.gl is creating a <div> and a <canvas> element between the <Box id='mapcontainer'> div and the <DeckGL id='deck-gl'> div, and I can not get the div and canvas to live inside of their parent Box.
The id of the <div> and the <canvas> appear to be created from the id passed into the DeckGL component, id="deck-gl-wrapper" and id="deck-gl" respectively. Where "deck-gl" is the id I passed into the <deckGL> component.
That may or may not be the actual problem, but using the elements inspector in devtools that is my best guess right now.
Can anyone help me figure out why deck.gl and react-map-gl components are not living within their parent bounds? Even when I set the parent and/or canvas props in the DeckGL component?
Documentation links:
react-map-gl
deck.gl
A functioning example is included in the codesandbox linked above. I have included many of the things I have tried as comments but no luck so far.
https://codesandbox.io/s/deck-gl-and-mui-react-e3t23?file=/src/App.js
Thank you...
For local quick reference, the app.js file looks something like this.
import Box from "#material-ui/core/Box";
import DeckGL from "#deck.gl/react";
import { MapView } from "#deck.gl/core";
import { LineLayer } from "#deck.gl/layers";
import { StaticMap } from "react-map-gl";
const MAPBOX_ACCESS_TOKEN = <tokenInCodeSandboxIfYouNeedIt>
const INITIAL_VIEW_STATE = {
longitude: -122.41669,
latitude: 37.7853,
zoom: 13,
pitch: 0,
bearing: 0
};
const data = [
{
sourcePosition: [-122.41669, 37.7853],
targetPosition: [-122.41669, 37.781]
}
];
function App() {
return (
<Box
id='mapcontainer'
sx={{
border: 1,
height: 450,
width: "auto",
m: 5
}}
>
<DeckGL
initialViewState={INITIAL_VIEW_STATE}
controller={true}
id="deck-gl"
>
<LineLayer id="line-layer" data={data} />
<MapView
id="map"
controller={false}
>
<StaticMap
mapStyle="mapbox://styles/mapbox/dark-v9"
mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN}
/>
</MapView>
</DeckGL>
</Box>
);
}
export default App;
In order to allow the deck.gl component to take up the available space of the parent component you can add position: 'relative' into the overrides for your Box with an id of mapcontainer.
Hello this is for a React/Gatsby website i'm working on.
I'm searching for a way to animate the child paragraph of a div using only CSS transition:
<div>
<p>{excerpt}</p>
</div>
Where excerpt is a variable i'm changing via Javascript when the cursor hovers the parent <div>.
This is the simplified React component. excerpt is a React state:
import React, { useState } from 'react'
const PostExcerpt = ({ post, featured }) => {
const [excerpt, setExcerpt] = useState(post.shortExcerpt)
const handleHover = (event, hover) => {
event.preventDefault()
if (hover) setExcerpt(post.longExcerpt)
else setExcerpt(post.shortExcerpt)
}
return (
<div
onPointerOver={(event) => {
handleHover(event, true)
}}
onPointerOut={(event) => {
handleHover(event, false)
}}
>
<p>{excerpt}</p>
</div>
)
}
export default PostExcerpt
The height of the <p> is adjusted automatically when content changes and i would like to animate the height change.
How can I transition height: 0; to height: auto; using CSS? doesn't apply because the height of my element is always set to auto. It simply changes because it follows content dimensions.
Basically, I'm creating a form component that is contained inside a v-dialog. The form component will have different child components that are rendered based on select input. So I have to set width of v-dialog to "unset", so that the width of the dialog will stretch to match its content.
The transition works when I toggle the value of width, eg: either 450px or 300px. The problem is that I don't know beforehand the width of the form contains in the dialog, so I definitely need to use dynamic width.
So far, I can not find anyways to achieve transition when using dynamic width. I was trying to get the width of the form component using refs, but setting width to unset, prevent the transition. By the way, the transition I'm talking about is the transition of the width, when using fixed width, it shows nice transition but not for dynamic width
<div id="app">
<v-app id="inspire">
<div class="text-center">
<v-dialog v-model="dialog" width="unset">
<template v-slot:activator="{ on }">
<v-btn color="red lighten-2" dark v-on="on">
Click Me
</v-btn>
</template>
<v-card>
<v-select v-model="selectedForm" :items="items">
</v-select>
<div v-if="selectedForm==='form-a'" class='form-a'>FormA</div>
<div v-if="selectedForm==='form-b'" class='form-b'>FormB</div>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" text #click="dialog = false">
I accept
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</v-app>
</div>
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
selectedForm: "form-a",
items: ["form-a", "form-b"],
dialog: false
};
}
});
codepen for using fixed width: https://codepen.io/duongthienlee/pen/MWaBLXm
codepen for using dynamic width: https://codepen.io/duongthienlee/pen/GRpBzmL
Noted that in the example i made in codepen, I defined width already, but the real case is that I don't know beforehand the width of form-a and form-b component. form-a and form-b width will be inherited by its parent div which is v-dialog, so that's why I set the width of v-dialog to be unset.
An example of what I mean "dynamic width": form-a has a select input. When user chooses an item, there will be a request to server to get input labels. So form-a will render multiple input fields based on the response body from server. The response body will contain label and default values information. So that makes the width of form-a becomes dynamic.
I think something like this can work for you.
Change v-dialog like so:
<v-dialog v-model="dialog" :width="forms.find(x => x.name===selectedForm).width">
Modify data() to return a forms prop:
data() {
return {
selectedForm: "form-a",
items: ["form-a", "form-b"],
dialog: false,
forms: [
{
name: 'form-a',
width: 200
},
{
name: 'form-b',
width: 1000
}
]
};
}
What you want to do is get the size of the rendered form, and then apply it to the dialog.
This is a common theme when attempting to animate content with dynamic dimensions.
One way to do this is by:
Set the form's visibility as hidden
Wait for it to render
Get the form's width and set it to the dialog
Unset the form's visibility
The tricky/hacky part is that you have to properly await DOM (setTimeout) and Vue ($nextTick) recalculations. I didn't have to await for Vue's $nextTick in this example, but you probably will if you're rendering nested form components:
<div class="form-container">
<div :style="formStyle('form-a')" class='form-a' ref="form-a">FormA</div>
<div :style="formStyle('form-b')" class='form-b' ref="form-b">FormB</div>
</div>
computed:{
formStyle(){
return form => ({
visibility: this.selectedForm == form ? 'inherit' : 'hidden',
position: this.selectedForm == form ? 'inherit' : 'absolute'
})
}
},
methods: {
async onSelectChange(form){
// async request
await new Promise(resolve => setTimeout(resolve, 1000))
this.selectedForm = form
this.recalculate()
},
async recalculate(){
// wait for DOM to recalculate
await new Promise(resolve => setTimeout(resolve))
const formEl = this.$refs[this.selectedForm]
this.dialogWidth = formEl.clientWidth
this.dialogHeight = formEl.clientHeight
},
...
}
Here's the working code to give you an idea:
https://codepen.io/cuzox/pen/yLYwoQo
If I understand you correctly, then this can be done using css. You can try replace all the fix width in the form with
width: fit-content;
For example in you codepen:
.form-a {
width: fit-content;
height: 350px;
background: blue;
}
.form-b {
width: fit-content;
height: 500px;
background: red;
}
The v-dialog renders into a div with class v-dialog:
It seems the animation only works when the the width is of known value, so it cannot be just "unset". The solution would be to get the width of the child element, and set the width of the v-dialog accordingly with a variable.
See VueJS get Width of Div on how to get the width of the child element.
Let me know if it works, I find this is very interesting.
I am trying to add a basic deck.gl (mapbox static map) to a react project - which I can do; however, once the map is loaded it takes up the entire page and any other information is hidden behind the map. For example, I have some text in a <p> above the map and it gets hidden behind the map, when it should show just above it.
Any attempt to resize the div that the map sits in has been unsuccessful:
margin-top, height etc..
The class is called DglMap
class DglMap extends Component {
render() {
const layers = [];
return (
<div className="dglMapStyle">
<DeckGL
initialViewState={initialViewState}
controller={true}
layers={layers}
>
<StaticMap mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN} />
</DeckGL>
</div>
);
}
}
added to a class called Content
class Content extends Component {
state = {};
render() {
return (
<div>
<BaseMap />
</div>
);
}
}
added to app.js
function App() {
return (
<Router>
<div>
<SomeText />
<Route exact path="/" component={MainContent} />
</div>
</Router>
);
}
export default App;
The file SomeText returns <div><p>SomeText</p></div>
The expected result is for the map to show underneath the text and not show on top of it. In another case I may want to resize the map to a specific size; for example 500x500px.
Any help appreciated and happy to elaborate.
Cheers!
In the part of Deck.Gl where the width and the height of the canvas is set,
there seems to be this code:
if (width || width === 0) {
width = Number.isFinite(width) ? `${width}px` : width;
this.canvas.style.width = width;
}
if (height || height === 0) {
height = Number.isFinite(height) ? `${height}px` : height;
this.canvas.style.position = 'absolute';
this.canvas.style.height = height;
}
which adds absolute positioning regardless of width and height, which might cause some fo your problems. Try adding left and top css styles to move the canvas. Resizing of the canvas should however work without any problems, see snippet below that works.
<DeckGL width={width} height={height}></DeckGL>
I have a website where I use a table to display some data. The issue is that when I view the website on smaller screens, the table is cut off and not all of the content is displayed. You can see below that despite me scrolling all the way to the right, the right most field is only barely visible and cut off by the screen.
I seem to partly be able to fix this by the width css parameter in root but if I set width too high, is just adds unnecessary right margin.
import React from 'react';
import {ListUsersTableRow} from "./listUserTableRow";
import { withStyles } from 'material-ui/styles';
import Table, { TableBody, TableCell, TableHead, TableRow } from 'material-ui/Table';
import Paper from 'material-ui/Paper';
const styles = theme => ({
root: {
[theme.breakpoints.up('md')]: {
width: `calc(100% - 140px)`,
},
marginTop: theme.spacing.unit * 3,
overflowX: 'auto',
},
table: {
minWidth: 700,
},
});
export const ListUsersTable = (props) => {
const { classes } = props;
return (
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>Edit</TableCell>
<TableCell>Full name</TableCell>
<TableCell>Username</TableCell>
<TableCell>Email</TableCell>
<TableCell>Company</TableCell>
<TableCell>Contact Number</TableCell>
<TableCell>Role</TableCell>
<TableCell>Status</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.users.map(user => <ListUsersTableRow key={user.id} {...user} toggleEdit={props.toggleEdit}/>)}
</TableBody>
</Table>
</Paper>
)
};
export default withStyles(styles)(ListUsersTable);
min-width is causing your table to be at least as wide as 700.
Try something simple like width: 100%;
If width:100%; messes up your side menu, you may want to consider setting the width of the menu to something like 30% instead of, say, 240px. With your menu taking up 30% of the page, and your table taking up the other 70%, things should fit a little better.
Rough guess without working example, though.