Scroll not working in overflowing content in Material UI - css

I am trying to map dummyData in div. The problem is the scroll doesn't work(especially in mobile screen) when data overflows out of the screen vertically. I tried using the Material UI list instead of div with no success. Here is the CodeSandbox.
import React from "react";
import makeStyles from "#material-ui/core/styles/makeStyles";
const useStyles = makeStyles(theme => ({
container: {
bottom: 0,
position: "fixed"
},
bubbleContainer: {
width: "100%"
},
bubble: {
border: "0.5px solid black",
borderRadius: "10px",
margin: "5px",
padding: "10px",
paddingTop: "150px",
paddingBottom: "150px",
display: "inline-block"
}
}));
const Demo = () => {
const classes = useStyles();
const dummyData = [
{
message: "Some random text"
},
{
message: "Some random text"
},
{
message: "Some random text"
},
{
message: "Some random text"
},
{
message: "Some random text"
}
];
const chatBubbles = dummyData.map((obj, i = 0) => (
<div className={classes.bubbleContainer}>
<div key={i++} className={classes.bubble}>
<div>{obj.message}</div>
</div>
</div>
));
return <div className={classes.container}>{chatBubbles}</div>;
};
export default Demo;

Related

I'm unable to have margins on either side for my FlatList

I'm trying to render a FlatList in my React Native application, but am running into some issues with my styles. I want to keep 3 items per row, and have 16px left and right margin on the list (so basically the sides of the FlatList should have 16px of margin on them). On top of that, I need to maintain spacing in between each item inside the flatlist.
I've got the spacing down, but the margins on the side of my FlatList are not working. I can't seem to get even margins on both side, without pushing the list off-screen.
My code is below, and here is a link to my code in a codesandbox.io editor.
import React from "react";
import {
Button,
Image,
useWindowDimensions,
StyleSheet,
FlatList,
TouchableOpacity,
Text,
View
} from "react-native";
function MyCustomComponent() {
const galleryItemGap = 8;
const { width } = useWindowDimensions();
const bookInfos = [
{
text: "Lorem Ipsum",
color: "red"
},
{
text: "Lorem Ipsum",
color: "green"
},
{
text: "Lorem Ipsum",
color: "blue"
},
{
text: "Lorem Ipsum",
color: "yellow"
},
{
text: "Lorem Ipsum",
color: "orange"
},
{
text: "Lorem Ipsum",
color: "pink"
}
];
const galleryItemWidth = (width - galleryItemGap * 3) / 3;
const memoizedStyles = React.useMemo(() => {
return {
bookContainer: {
marginTop: galleryItemGap,
marginLeft: galleryItemGap,
width: galleryItemWidth,
backgroundColor: "aqua",
...styles.bookContainer
},
book: {
width: galleryItemWidth,
...styles.book
}
};
}, [galleryItemGap, galleryItemWidth, styles.book, styles.bookContainer]);
const renderItem = React.useCallback(
({ item }) => {
return (
<View key={item.id} style={memoizedStyles.bookContainer}>
<TouchableOpacity style={{ backgroundColor: item.color }}>
<Text>{item.text}</Text>
</TouchableOpacity>
</View>
);
},
[memoizedStyles.book, memoizedStyles.bookContainer]
);
return <FlatList data={bookInfos} numColumns={3} renderItem={renderItem} />;
}
function App() {
return <MyCustomComponent />;
}
const styles = StyleSheet.create({
bookContainer: {
height: 180,
justifyContent: "center",
alignItems: "center"
},
book: {
height: 180
}
});
export default App;
My idea:
Add marginHorizontal to FlatList content.
Remove marginLeft: galleryItemGap and width: galleryItemWidth in bookContainer`
Add marginHorizontal and flex: 1 to middle item(index % 3 === 1) in renderItem
Example:
https://codesandbox.io/s/intelligent-wiles-4wugdg?file=/src/App.js

Applying css on a imported react component

I have a UserPreview component which have other components( avatar, bio, followstats). When, I am trying to style these components, nothing happens. I tried inline styling as well. But, Styling on a normal div is working perfectly fine. I have no idea why its happening.
import React from "react";
import Avatar from "../../Atoms/Avatar";
import Bio from "../../Atoms/Bio";
import FollowStats from "../../Atoms/FollowStats";
import Profile from "../../Assets/images/profile.jpg";
import useStyles from "./style";
const UserPreview = () => {
const classes = useStyles();
return (
<div className={classes.root}>
<Avatar
size="large"
image={Profile}
name="Aman"
username="dev_aman7"
className={classes.avatar}
style={{ border: "1px solid red" }}
/>
<Bio value="This is Bio" className={classes.bio} />
<div className={classes.edit}>Edit Profile</div>
<FollowStats followers={20} following={30} className={classes.follow} />
</div>
);
};
export default UserPreview;
Styles
import makeStyles from "#material-ui/styles/makeStyles";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
alignItems: "center",
maxWidth: "20rem",
flexDirection: "column",
paddingTop: "1rem",
},
avatar: {
padding: "5rem",
border: "1px solid black",
},
bio: {
marginTop: "1rem",
},
edit: {
color: theme.palette.blue,
fontSize: theme.f5,
margin: "auto",
marginTop: ".5rem",
},
follow: {
margin: "1.5rem",
width: "100%",
},
}));
export default useStyles;
Material ui is used as design library
Avatar.jsx
import React from "react";
import ClassNames from "classnames";
import PropTypes from "prop-types";
import useStyles from "./style";
const Avatar = ({ image, size, name, username }) => {
const classes = useStyles();
const container = ClassNames(
{ [classes.root_small]: size === "small" },
{ [classes.root_large]: size !== "small" }
);
const usernameClass = ClassNames(classes.username, {
[classes.grey]: size === "small",
});
const imgClass = ClassNames(
classes.img,
{ [classes.img_small]: size === "small" },
{ [classes.img_large]: size !== "small" }
);
return (
<div className={container}>
<div>
<img src={image} alt="Profile_image" className={imgClass} />
</div>
{size === "small" ? null : <div className={classes.name}>{name}</div>}
<div className={usernameClass}>#{username}</div>
</div>
);
};
Avatar.defaultProps = { name: "" };
Avatar.propTypes = {
image: PropTypes.string.isRequired,
size: PropTypes.string.isRequired,
name: PropTypes.string,
username: PropTypes.string.isRequired,
};
export default Avatar;
import { makeStyles } from "#material-ui/styles";
const useStyles = makeStyles((theme) => ({
root_small: {
display: "flex",
alignItems: "center",
},
root_large: {
maxWidth: "20rem",
textAlign: "center",
},
img: {
borderRadius: "50%",
},
img_small: {
height: "2.5rem",
width: "2.5rem",
marginRight: "1rem",
},
img_large: { width: "4.5rem", height: "4.5rem" },
name: {
fontSize: theme.f2,
fontWeight: theme.bold6,
marginTop: "0.5rem",
color: theme.palette.grey,
},
username: {
fontSize: theme.f4,
color: theme.palette.pinkGrey,
},
grey: {
color: theme.palette.grey,
},
}));
export default useStyles;

Material UI - set color for SVG

I use Material UI in ReactJS and have the following component to render an SVG:
import React, { FunctionComponent } from "react";
import SvgIconMUI from "#material-ui/core/SvgIcon";
import { SvgIconProps } from "./types";
import { ReactComponent as HelloWorld } from "Icon/Sections/icon-flat.svg";
const SvgIcon: FunctionComponent<SvgIconProps> = ({
slug,
classes,
svgIconViewBox = "0 0 96 96",
}) => {
const SpecificSpartenIcon = HelloWorld;
return (
SpecificSpartenIcon && (
<div className={classes.svgContainer}>
<SvgIconMUI viewBox={svgIconViewBox} className={classes.svgIcon}>
<SpecificSpartenIcon />
</SvgIconMUI>
</div>
)
);
};
export default SvgIcon;
What I want to achieve: set another color for the SVG.
What I have tried to change the color:
import { makeStyles, Theme } from "#material-ui/core";
interface Props {
colors: ExpertColor;
}
const svgIconViewBox = "0 0 96 96";
const selectedIconStyles = { fontSize: 30 };
const useStyles = makeStyles<Theme, Props>((theme: Theme) => ({
svgContainer: {
display: "flex",
justifyContent: "center",
position: "relative",
height: "100%",
width: "100%",
padding: 0,
fill: "red !important;",
color: "red !important;",
},
svgIcon: {
position: "absolute",
height: "55px",
width: "55px",
top: 0,
fill: "red !important;",
color: "red !important;",
},
}));
export default { useStyles, svgIconViewBox, selectedIconStyles };
It does not work. Do you have an idea ?

How to display three post photo div at the bottom of the page using Reactjs and Css

The code below has three posts photos in the array. When I click on each post button am supposed to be seeing
Three post Photo div that corresponds to each post all at the bottom.
My Problem:
My issue is that it is showing just one post photo div which keeps replacing others after I added the CSS code below.
const mainArea={
position: 'fixed',
width: '80%',
bottom: '0%',
display: 'inline-block'
}
const photodiv={
position: 'relative',
width: '250px',
// height:auto,
background: 'orange',
color: 'black',
borderRadius: '5px 5px 0px 0px',
bottom: '0px',
}
screenshot showing jammed div based on the CSS implementation
What I want:
I need to be seeing three div post photos if the three toggle button is clicked
Here is the main code
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
const mainArea={
position: 'fixed',
width: '80%',
bottom: '0%',
display: 'inline-block'
}
const photodiv={
position: 'relative',
width: '250px',
// height:auto,
background: 'orange',
color: 'black',
borderRadius: '5px 5px 0px 0px',
bottom: '0px',
}
class Focus extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
shown: true,
};
}
componentDidMount() {
this.setState({
data: [
{ id: "1", title: "my first title", image: "http://localhost/apidb_react/1.png", visible: true , photoVisible: true},
{ id: "2", title: "my second title", image: "http://localhost/apidb_react/2.png", visible: true, photoVisible: true},
{ id: "3", title: "my third title", image: "http://localhost/apidb_react/3.png", visible: true, photoVisible: true}
]
});
}
toggle(id) {
const newData = this.state.data.map(item => {
if(item.id === id) {
return { ...item, visible: !item.visible};
}
return item;
})
this.setState({
data: newData
});
}
/*
hideUnhidePhoto(id) {
const newData = this.state.data.map(item => {
alert(id);
if(item.id === id) {
alert('ttto ' +item.id);
return { ...item, photoVisible: !item.photoVisible};
}
return item;
})
this.setState({
data: newData
});
}
*/
hideUnhidePhoto(id) {
this.setState(({ data }) => {
return {
data : data.map(item => ({
...item,
photoVisible : (id == item.id) ? !item.photoVisible : item.photoVisible }))
}
});
}
render() {
return (
<div>
<label>
<ul>
{this.state.data.map((post, i) => (
<li key={i}>
<div style={mainArea}>
<div style={photodiv}>
<div style={{ display: post.visible ? "none" : "block"}}>
<b>Post Data:</b> {post.title} --{post.id} <br />
<span style={{color: 'red'}} onClick={ () => this.hideUnhidePhoto(post.id) }> Hide/Unhide Photo</span>
<div style={{ display: post.photoVisible ? "block" : "none"}}>
<img src={post.image} />
</div>
</div></div>
</div>
<button onMouseDown={ () => this.toggle(post.id) }>Toggle </button><br />
<br />
</li>
))}
</ul>
</label>
</div>
);
}
}
If I understand the issue correctly, then this can be fixed by adjusting your mainArea style object like so:
const mainArea={
/* position: 'fixed', Remove position fixed */
width: '80%',
bottom: '0%',
display: 'inline-block'
}
The fixed position basically has the effect of placing elements at a location on screen, relative to the client area of the window. This means that if you have multiple elements that share the same (default) coordinates, and are positioned with the fixed rule, then those elements will effectively overlap one another. This gives the appearance of only one element being visible at any given time.
For a working example, see this jsFiddle:
enter link description here
Hope that helps!

How to make Material-UI Snackbar not take up the whole screen width using anchorOrigin?

I have a class in React which uses an input field which is part of the website header:
If the input is invalid then I want to display a snackbar. I'm using Material-UI components.
The problem is I defined anchorOrigin to be center and top as per Material-UI API. However the snackbar takes up the whole screen width while I want it to only take up the top center location of the screen. My message is quite short, for example "Value invalid" but if it's longer then I should be able to use newlines. I'm not sure if there's some setting in Material-UI API to alter this (I couldn't find one) or I need to use CSS.
This is my code:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import InputBase from '#material-ui/core/InputBase';
import Snackbar from '#material-ui/core/Snackbar';
import SnackbarMessage from './SnackbarMessage.js';
const classes = theme => ({
inputRoot: {
color: 'inherit',
width: '100%',
},
inputInput: {
paddingTop: theme.spacing.unit,
paddingRight: theme.spacing.unit,
paddingBottom: theme.spacing.unit,
paddingLeft: theme.spacing.unit * 10,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('sm')]: {
width: 120,
'&:focus': {
width: 200,
},
},
}
});
class Test extends Component {
state = {
appId: '',
snackBarOpen: false
}
render() {
return (
<div>
<InputBase
placeholder="Search…"
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
value={'test'} />
<Snackbar
anchorOrigin={{
vertical: 'top',
horizontal: 'center'
}}
open={true}
autoHideDuration={5000}
>
<SnackbarMessage
variant="warning"
message={"test message"}
/>
</Snackbar>
</div>
)
}
}
Material-UI set Snackbars to full viewport-width below the breakpoint "md" (600px).
You can use overrides (https://material-ui.com/customization/overrides/) and set new values to the default CSS classes of the component described in the components API (i.e. https://material-ui.com/api/snackbar/). So you can override the class anchorOriginTopCenter as follows:
const styles = theme => ({
anchorOriginTopCenter: {
[theme.breakpoints.down('md')]: {
top: "your value/function here",
justifyContent: 'center',
},
},
root: {
[theme.breakpoints.down('md')]: {
borderRadius: 4,
minWidth: "your value / function here",
},
},
});
The first objects overrides the default class {anchorOriginTopCenter}, the second 'root' is applied to first element in your snackbar (probably a 'div').
I do not know if we can add some style to the component anchor origin field. I think the div needs to be managed using CSS. It's an anchor, not style.
<Snakbar
className = "my-snakbar"
{/*All your other stuff*/}
>
{//Stuff}
</Snakbar>
CSS
.my-snakbar {
width: 200px;
//Maybe use flexbox for positioning then
}
Let me know your thoughts
Daniel
Improved Answer
Code copied from origional question and modified
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Snackbar from '#material-ui/core/Snackbar';
const classes = theme => ({
inputRoot: {
color: 'inherit',
width: '100%',
},
inputInput: {
paddingTop: theme.spacing.unit,
paddingRight: theme.spacing.unit,
paddingBottom: theme.spacing.unit,
paddingLeft: theme.spacing.unit * 10,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('sm')]: {
width: 120,
'&:focus': {
width: 200,
},
},
}
});
class ComingSoon extends Component {
render() {
const styles = {
container: {
position: "fixed",
top: "0px",
width: "100%",
height: "30px"
},
snakbar: {
background: "black",
color: "white",
width: "100px",
height: "100%",
display: "flex",
justifyContent: "center",
alignContent: "center",
margin: "0 auto"
}
};
return (
<div className = "snakbar-container" style = {styles.container}>
<Snackbar
className = "my-snakbar"
style = {styles.snakbar}
anchorOrigin={{
vertical: 'top',
horizontal: 'center'
}}
open={true}
autoHideDuration={5000}
>
<span>My Message</span>
</Snackbar>
</div>
)
}
}
export default ComingSoon;
Screen shot:
Let me know if this helped
Daniel

Resources