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 ?
Related
I want to set a default background color that will apply to all created pages in my project.
I have tried the following tutorial: https://itnext.io/next-js-with-material-ui-7a7f6485f671 but it does not work and gives this error: Error
Here are my files:
Index.tsx file:
import LoginPage from "./login";
export default function Start() {
return (<div ><LoginPage></LoginPage></div>);
}
Login.tsx file
import Typography from "#mui/material/Typography"
import React from 'react';
import { makeStyles } from '#mui/styles';
import { Button, TextField } from "#mui/material";
const useStyles = makeStyles(theme => ({
root: {
display: "inline-grid",
margin: "auto",
position:"fixed",
top: "50%",
left: "50%",
width:"30em",
height:"18em",
marginTop: "-9em",
marginLeft: "-15em",
border: "1px solid #ccc",
},
loginButton: {
border: "1px solid #ccc",
width: "30%",
height: "80%",
margin: "auto"
},
loginText: {
margin: "auto"
}
}));
export default function LoginPage() {
const classes = useStyles();
return (
<>
<div className={classes.root}>
<Typography className ={classes.loginText}>Login</Typography>
<TextField id="filled-basic" label="Email Adresse" variant="standard"></TextField>
<TextField id="filled-basic" label="Passwort" variant="standard" />
<Button className={classes.loginButton}>Login</Button>
</div>
</>
);
}
useTheme.ts file:
import { createTheme } from "#mui/material/styles";
// Create a theme instance.
const theme = createTheme ({
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
background: {
default: '#fff',
},
},
});
export default theme;
_app.tsx and _document.tsx are the same as in the tutorial provided in the link above
That's how my folder looks like with all files in
How can I fix the error that I am getting?
I am using React Native Typescript for my. In My app there are three elements one is Map, bottom-sheet (which position is absolute) and One button. I have created one custom bottom sheet. Bottom-sheet is animated Scrollable. Inside the Bottom-sheet I used Custom search bar and under the search bar there is Flat-list where I am rendering the data. In IOS simulator I can see the FlatList card under the Button. which is really bad from UI (IOS-Image) but in Android it looks perfect Android-simulator. I want to hide the flat-List data which is coming under the button. I tried background color white and tried with height, width, bottom.But none of of work. I want to make efficient css position instead of hard code position. But I don't know how to fixed it.
I share my code in Expo-snacks
This is my custom Bottom-sheet
import React from "react";
import {
SafeAreaView,
StyleSheet,
Text,
useWindowDimensions,
TouchableOpacity,
View,
} from "react-native";
import Animated, {
Extrapolate,
interpolate,
useAnimatedGestureHandler,
useAnimatedStyle,
withTiming,
} from "react-native-reanimated";
import { PanGestureHandler } from "react-native-gesture-handler";
import styled from "styled-components/native";
interface Props {
panY: number;
children: React.ReactNode;
}
export default function BottomSheet({ panY, children }: Props) {
const { height } = useWindowDimensions();
const gestureHandler = useAnimatedGestureHandler(
{
onStart(_, context) {
context.startY = panY.value;
},
onActive(event, context) {
panY.value = context.startY + event.translationY;
},
onEnd() {
if (panY.value < -height * 0.4) {
panY.value = withTiming(-(height * 0.6));
} else {
panY.value = withTiming(0);
}
},
},
[height]
);
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: interpolate(panY.value, [-1, 0], [-1, 0], {
extrapolateLeft: Extrapolate.EXTEND,
extrapolateRight: Extrapolate.CLAMP,
}),
},
],
};
});
return (
<PanGestureHandler onGestureEvent={gestureHandler}>
<Animated.View
style={[styles.container, { top: height * 0.7 }, animatedStyle]}
>
{children}
</Animated.View>
</PanGestureHandler>
);
}
const styles = StyleSheet.create({
container: {
position: "absolute",
top: 0,
left: 0,
right: 0,
backgroundColor: "white",
shadowColor: "black",
shadowOffset: {
height: -6,
width: 0,
},
shadowOpacity: 0.1,
shadowRadius: 5,
borderTopEndRadius: 15,
borderTopLeftRadius: 15,
},
});
This is My App component
import React, { useState } from "react";
import {
StyleSheet,
Text,
View,
Dimensions,
useWindowDimensions,
SafeAreaView,
StatusBar,
RefreshControl,
} from "react-native";
import styled from "styled-components/native";
import MapView from "react-native-maps";
import { useSharedValue } from "react-native-reanimated";
import { FlatList } from "react-native-gesture-handler";
import BottomSheet from "./ActionSheet";
import BottomButton from "./BottomButton";
import SafeAreaWrapper from "./SafeAreaWrapper";
import SearchBar from "./SearchBar";
const { width, height } = Dimensions.get("screen");
const api =
"http://open-api.myhelsinki.fi/v1/events/?distance_filter=60.1699%2C24.9384%2C10&language_filter=en&limit=100";
const initialRegion = {
latitudeDelta: 15,
longitudeDelta: 15,
latitude: 60.1098678,
longitude: 24.7385084,
};
export default function App() {
const { width, height } = useWindowDimensions();
const [loading, setLoading] = useState(false);
const [data, setData] = React.useState([]);
const updateState = async () => {
try {
const response = await fetch(api);
const data = await response.json();
setData(data.data);
} catch (error) {
console.log("failed to catch", error);
}
};
React.useEffect(() => {
updateState();
}, []);
const y = useSharedValue(0);
return (
<SafeAreaWrapper>
<Container>
<MapContent>
<MapView style={styles.mapStyle} initialRegion={initialRegion} />
</MapContent>
<BottomSheet panY={y}>
<Content>
<SearchContainer>
<SearchBar placeholder={"write some thing"} />
</SearchContainer>
{data && data === undefined ? (
<Text>loading</Text>
) : (
<HeroFlatList
data={data}
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl
enabled={true}
refreshing={loading}
onRefresh={updateState}
/>
}
keyExtractor={(_, index) => index.toString()}
renderItem={({ item, index }) => {
const image = item?.description.images.map((img) => img.url);
const startDate = item?.event_dates?.starting_day;
return (
<EventContainer key={index}>
<EventImage
source={{
uri:
image[0] ||
"https://res.cloudinary.com/drewzxzgc/image/upload/v1631085536/zma1beozwbdc8zqwfhdu.jpg",
}}
/>
<DescriptionContainer>
<Title ellipsizeMode="tail" numberOfLines={1}>
{item?.name?.en}
</Title>
<DescriptionText>
{item?.description?.intro ||
"No description available"}
</DescriptionText>
<DateText>{startDate}</DateText>
</DescriptionContainer>
</EventContainer>
);
}}
/>
)}
</Content>
</BottomSheet>
<ButtonContainer>
<BottomButton
title={"Save"}
onPress={() => {
console.log("jjj");
}}
/>
</ButtonContainer>
</Container>
</SafeAreaWrapper>
);
}
const styles = StyleSheet.create({
mapStyle: {
width: width,
height: height, // I DON'T KNOW HOW TO CONVERT THEM INTO STYLED COMPONENT
},
});
const HeroFlatList = styled(FlatList).attrs({
contentContainerStyle: {
paddingTop: 20,
paddingBottom: 2000, // BAD PRACTICE
flexGrow: 1, //SEEMS LIKE IT DOES NOT WORK
},
})`
height: 2000px; // BAD PRACTICE
`;
const MapContent = styled.View`
flex: 1;
`;
const Content = styled.View`
flex: 1;
padding: 20px;
`;
const Container = styled.View`
flex: 1;
`;
const ButtonContainer = styled.View`
background-color: #fdfbfb; // My Button container
`;
const TextName = styled.Text`
color: orange;
font-weight: bold;
`;
const SearchContainer = styled.View`
margin-bottom: 5px;
`;
const Title = styled.Text`
font-size: 16px;
font-weight: 700;
margin-bottom: 5px;
`;
const DescriptionText = styled(Title)`
font-size: 14px;
opacity: 0.7;
`;
const DateText = styled(Title)`
font-size: 14px;
opacity: 0.8;
color: #0099cc;
`;
const EventImage = styled.Image`
width: 70px;
height: 70px;
border-radius: 70px;
margin-right: 20px;
`;
const DescriptionContainer = styled.View`
width: 200px;
`;
const EventContainer = styled.View`
flex-direction: row;
padding: 20px;
margin-bottom: 10px;
border-radius: 20px;
background-color: rgba(0, 0, 0, 0.8);
`;
I am trying to override the default styles in a Mui component using the classes prop and passing the css into it. So far I have been unsuccessful and I'm not sure what I have wrong.
The motivation for not using makeStyles is to keep our files cleaner and Emotion is faster.
I am able to do it successfully using makeStyles like this:
import { css } from '#emotion/react';
import HelpIcon from '#material-ui/icons/Help';
import { Tooltip } from '#material-ui/core';
import ClickAwayListener from '#material-ui/core/ClickAwayListener';
import { useState } from 'react';
import { cbNeutral } from '../../src/theme/palette';
import { makeStyles } from '#material-ui/core/styles';
import PropTypes from 'prop-types';
const useStyles = makeStyles(() => ({
arrow: {
'&:before': {
border: `1px solid ${cbNeutral[900]}`
},
color: cbNeutral[1000]
},
tooltip: {
backgroundColor: cbNeutral[1000],
border: `1px solid ${cbNeutral[900]}`,
color: cbNeutral[400],
boxShadow: '0px 8px 16px 0px rgba(14, 13, 38, 0.12)',
maxWidth: '385px',
fontSize: '1.125rem',
padding: '18px 25px',
fontWeight: 400
},
root: {
fill: cbNeutral[700],
'&:hover': {
fill: cbNeutral[400],
cursor: 'pointer'
}
}
}));
const ToolTip = ({ text }) => {
const styles = useStyles();
const [open, setOpen] = useState(false);
return (
<ClickAwayListener onClickAway={() => setOpen(false)}>
<Tooltip
arrow
title={text}
placement="right-start"
open={open}
classes={{
arrow: styles.arrow,
tooltip: styles.tooltip
}}
>
<HelpIcon onClick={() => setOpen(true)} classes={{ root: styles.root }} />
</Tooltip>
</ClickAwayListener>
);
};
export default ToolTip;
ToolTip.propTypes = {
text: PropTypes.string.isRequired
};
I am trying to do it with Emotion like this:
import { css } from '#emotion/react';
import HelpIcon from '#material-ui/icons/Help';
import { Tooltip } from '#material-ui/core';
import ClickAwayListener from '#material-ui/core/ClickAwayListener';
import { useState } from 'react';
import { cbNeutral } from '../../src/theme/palette';
import { makeStyles } from '#material-ui/core/styles';
import PropTypes from 'prop-types';
const toolTipCss = css`
.arrow {
color: ${cbNeutral[1000]};
&:before {
border: 1px solid ${cbNeutral[900]};
}
}
.tooltip {
background-color: ${cbNeutral[1000]};
border: 1px solid ${cbNeutral[900]};
color: cbNeutral[400];
box-shadow: 0px 8px 16px 0px rgba(14, 13, 38, 0.12);
max-width: 385px;
font-size: 1.125rem;
padding: 18px 25px;
font-weight: 400;
}
.help-icon {
fill: ${cbNeutral[700]};
&:hover {
fill: ${cbNeutral[400]};
cursor: pointer;
}
}
`;
const ToolTip = ({ text }) => {
const [open, setOpen] = useState(false);
return (
<div css={toolTipCss}>
<ClickAwayListener onClickAway={() => setOpen(false)}>
<Tooltip
arrow
title={text}
placement="right-start"
open={open}
classes={{
arrow: 'arrow',
tooltip: 'tooltip'
}}
>
<HelpIcon onClick={() => setOpen(true)} className="help-icon" />
</Tooltip>
</ClickAwayListener>
</div>
);
};
export default ToolTip;
ToolTip.propTypes = {
text: PropTypes.string.isRequired
};
In 👆 that version where I use className="help-icon", it works as expected, but classes={{arrow: 'arrow', tooltip: 'tooltip'}} does not change the default MUI styles.
I am using these versions of MUI and Emotion
"#emotion/react": "^11.4.0",
"#material-ui/core": "^4.11.4",
I know we have it working like this in another app using older versions of MUI and emotion. I don't know if something has changed in the mean time or of I just have something wrong with my syntax. Any help would be appreciated.
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;
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;