For example, how to accomplish
box-shadow: 2px 2px 4px rgba(0, 0, 0, .05), -2px -2px 4px rgba(0, 0, 0, .05);
in react native stylesheet?
I don't think you can, but the hack of wrapping your component with another just for another layer of shadow is the worst hack of the century either:
<div style={{ boxShadow: "2px 2px 4px rgba(0, 0, 0, .05)"}}>
<div style={{ boxShadow: "-2px -2px 4px rgba(0, 0, 0, .05)"}}>
{ content }
</div>
</div>
I created a react component that automatically creates multiple View components for every shadow you need. It is likely to have some quirks, but it worked fine for my situation.
import React from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import * as _ from 'lodash';
const partitionByKeys = (keys, obj) => {
let pass = {};
let fail = {};
for (const key of Object.keys(obj)) {
if (keys.includes(key)) {
pass[key] = obj[key];
} else {
fail[key] = obj[key];
}
}
return [pass, fail];
};
const innerStyleKeys = [
'padding', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight',
'paddingHorizontal', 'paddingVertical',
'backgroundColor', 'flexDirection', 'justifyContent', 'alignItems',
'minHeight', 'minHeight',
];
const ShadowView = ({ level = 0, shadows, children, style, ...props }) => {
const shadow = _.head(shadows);
const [innerStyle, outerStyle] = style ? partitionByKeys(innerStyleKeys, style) : [{}, {}];
return (
<View
{...props}
style={{
shadowColor: shadow.color,
shadowOffset: shadow.offset,
shadowOpacity: shadow.opacity,
shadowRadius: shadow.radius,
...(level === 0 ? outerStyle : {}),
...(shadows.length === 1 ? innerStyle : {}),
}}
>
{ shadows.length === 1 ?
children :
<ShadowView level={level + 1} shadows={_.tail(shadows)} style={style}>{children}</ShadowView>
}
</View>
);
};
export default ShadowView;
Usage:
<ShadowView shadows={[{
color: '#FF0000',
opacity: 0.5,
offset: {
width: 0,
height: 10,
},
radius: 60,
}, {
color: '#00FF00',
opacity: 0.5,
offset: {
width: 0,
height: 3,
},
radius: 20,
}]}>...</ShadowView>
Related
I have a project using next.js and tailwind v2.2. When I installed tailwind and imported to _app.tsx, everything was ok and it works in _app.tsx and components which is in components folder. But when I try to use tailwind custom classes in sub folder of components folder, It doesn't work!
For example it works in footer.tsx component but doesn't work in files that are indexComponents (Picture below)
tailwind.confing.js:
// tailwind.config.js
module.exports = {
mode: "jit",
purge: ['./pages/**/*.{js,ts,jsx,tsx}','./components/**/*.{js,ts,jsx,tsx}','./components/indexComponents/*.{js,ts,jsx,tsx}'] ,
darkMode: false, // or 'media' or 'class'
theme: {
colors: {
// blue-mode
// "color-50": "#eff6ff",
// "color-100": "#dbeafe",
// "color-200": "#bfdbfe",
// "color-300": "#93c5fd",
// "color-400": "#60a5fa",
// "color-500": "#3b82f6",
// "color-600": "#2563eb",
// "color-650": "#086ad8",
// "color-700": "#1d4ed8",
// "color-800": "#1e40af",
// "color-900": "#1e3a8a",
// purple mode
"color-50": "#faf5ff",
"color-100": "#f3e8ff",
"color-200": "#e9d5ff",
"color-300": "#d8b4fe",
"color-400": "#c084fc",
"color-500": "#a855f7",
"color-600": "#9333ea",
"color-650": "#9333ea",
"color-700": "#7e22ce",
"color-800": "#6b21a8",
"color-900": "#581c87"
},
screens: {
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1200px",
"2xl": "1200px"
},
container: {
center: true,
padding: "1rem"
},
fontFamily: {
heading: ["Poppins, sans-serif"],
body: ["Montserrat, sans-serif"]
},
boxShadow: {
sm: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
DEFAULT: "0px 2px 4px rgba(148, 163, 184, 0.05), 0px 6px 24px rgba(235, 238, 251, 0.4)",
md: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
lg: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
xl: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
"2xl": "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
"3xl": "0 35px 60px -15px rgba(0, 0, 0, 0.3)",
inner: "inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)",
none: "none"
},
fontSize: {
xs: ".75rem",
sm: ".875rem",
tiny: ".875rem",
base: "1rem",
lg: "1.125rem",
xl: "1.25rem",
"2xl": "1.5rem",
"3xl": "1.875rem",
"4xl": ["2.25rem", "3.2rem"],
"5xl": ["3rem", "4rem"],
"6xl": ["4rem", "1rem"],
"7xl": ["5rem", "1rem"],
"10xl":"6rem"
},
extend: {
keyframes:{
modalDown:{
'0%,50%':{marginTop:-300},
'50%,100%':{marginTop:0}
}
},
animation:{
modalDown:'modalDown 0.5s linear'
},
width: {
'3/4': '75%',
},
colors: {
white: "#ffffff",
body: "#1e293b",
//blue-mode
// "colorGray-50": "#f8fafc",
// "colorGray-100": "#f1f5f9",
// "colorGray-200": "#e2e8f0",
// "colorGray-300": "#cbd5e1",
// "colorGray-400": "#94a3b8",
// "colorGray-500": "#64748b",
// "colorGray-600": "#475569",
// "colorGray-700": "#334155",
// "colorGray-800": "#1e293b",
// "colorGray-900": "#0f172a",
// "primary": "rgb(96,165,250)",
// //purple mode
"colorGray-50": "#f5f3ff",
"colorGray-100": "#ede9fe",
"colorGray-200": "#ddd6fe",
"colorGray-300": "#cbd5e1",
"colorGray-400": "#a78bfa",
"colorGray-500": "#64748b",
"colorGray-600": "#475569",
"colorGray-700": "#6d28d9",
"colorGray-800": "#5b21b6",
"colorGray-900": "#4c1d95",
"primary":"rgb(96,165,250)",
},
height: {
"128": "32rem"
},
}
},
important: true,
variants: {
extend: {}
},
plugins: []
};
For example I have 'text-color-400' custom class that works in _app.tsx and doesn't work in the components of indexComponents.When I inspect the element don't see anything from globals.css
globals.css:
/*tailwindcss utility classes*/
#tailwind base;
#tailwind components;
#tailwind utilities;
I tried change the purge to:
['./pages/**/*.{js,ts,jsx,tsx}','../public/components/**/*.{js,ts,jsx,tsx}','../public/components/indexComponents/*.{js,ts,jsx,tsx}']
But I have the same problem!
This question already has an answer here:
how to apply global backgroundColor using MuiCssBaseline and styleOverrides
(1 answer)
Closed 10 months ago.
I'm using the latest MUI version (v5) and CssBaseline from #mui/materials and given how I normally do this in CSS:
body, html, #root {
width: 100%;
height: 100%;
min-height: 100%;
margin: 0;
padding: 0;
font-size: 62.5%; /* makes 1.2rem === 12px, 1.6rem === 16px, ect... */
text-align: left;
}
MUI Body
(add the following to my theme)
components: {
MuiCssBaseline: {
styleOverrides: {
body: {
width: '100%',
height: '100%',
minHeight: '100%',
margin: 0,
padding: 0,
fontSize: '62.5%', // makes 1.2rem === 12px, 1.6rem === 16px, ect...
textAlign: 'left'
}
}
}
}
MUI Root
(add the following to my sxStyle e.g: sx={{...sxLayout, ...sxLayout.root}})
const sxLayout = {
flexDirection: 'column',
root: {
width: '100%',
height: '100%',
minHeight: '100%',
margin: 0,
padding: 0,
fontSize: '62.5%', // makes 1.2rem === 12px, 1.6rem === 16px, ect...
textAlign: 'left',
'&': {
width: '100%',
height: '100%',
minHeight: '100%',
margin: 0,
padding: 0,
fontSize: '62.5%', // makes 1.2rem === 12px, 1.6rem === 16px, ect...
textAlign: 'left'
},
'&.MuiListItemButton-root': {
width: '100%',
height: '100%',
minHeight: '100%',
margin: 0,
padding: 0,
fontSize: '62.5%', // makes 1.2rem === 12px, 1.6rem === 16px, ect...
textAlign: 'left'
}
}
}
MUI Html
(????)
????
There are a few ways to get components styled. The last one I describe is specific to MUI and is probably likeliest to be what you are looking for.
Some of the css classes belong to specific MUI components, so you just use the MUI component and if your <ThemeProvider /> is used correctly, you shouldn't have to add any classes.
You have the option of defining regular CSS or SASS in a separate file and importing it in your component, then using the class via the className property of a component.
Another option is CSS-in-JS. You can use the style property to use the custom css and you define the CSS in your JS file for the component:
... //inside your component
const mystyle = {
color: "white",
backgroundColor: "DodgerBlue",
padding: "10px",
fontFamily: "Arial"
};
...
return (
<div>
<h1 style={mystyle}>Hello Style!</h1>
<p>Add a little style!</p>
</div>
);
...
Above example adapted from https://www.w3schools.com/react/react_css.asp
The above work in react without MUI as well. The MUI specific way to create a custom style for a component is to use the makeStyles() hook. This will give you variables to use as input to the className property but when you inspect and look at the html, the classes applied will have names that are generated by MUI.
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
const useStyles = makeStyles({
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
color: 'white',
height: 48,
padding: '0 30px',
},
});
export default function MyComponent() {
const classes = useStyles();
return <Button className={classes.root}>Hook</Button>;
}
Above example copied from https://react.school/material-ui/styling
To learn more about the makeStyles() hook, see the MUI documentation for it: https://mui.com/system/styles/api/#makestyles-styles-options-hook
If you scroll on that same page, you can see info about other style related hooks too.
I am using a Material UI React component called TextareaAutosize:
<TextareaAutosize
minRows={2}
style={resize: 'none'}
defaultValue={<span style={{fontSize: "20px", color: "blue"}}>Content Body</span>}
/>
Instead of getting Content Body in the TextareaAutosize component, I'm getting this as the default value:
How do I add styling to the defaultValue?
Edit code on Stack Blitz: https://stackblitz.com/edit/react-fnx6we?file=demo.js
EDIT: For clarification, I want ONLY the defaultValue to have the styling I applied. When the user starts typing or removes the defaultValue and starts typing, the styling of the defaultValue should NOT be applied.
defaultValue parameter accepts String values only. Use parameter style to define additional styling. Or use jss like styling for components (check #mui/styles) EDIT: to change styling of the element "on the fly" you will need to use additional variables and functions. Check demo on code on Stack Blitz.
import React, { useState } from 'react';
import TextareaAutosize from '#mui/material/TextareaAutosize';
import { makeStyles } from '#mui/styles';
const useStyles = makeStyles({
textAreaWithStyle: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
color: 'white',
height: 48,
padding: '0 30px',
fontSize: '20px',
color: 'blue',
resize: 'none',
},
textAreaWithoutStyle: {
resize: 'none',
},
});
export default function MaxHeightTextarea() {
const classes = useStyles();
const [valueOfInput, setValueOfInput] = useState('Default Text');
const returnStyleBasedOnInput = () => {
if (valueOfInput === 'Default Text') {
return classes.textAreaWithStyle;
} else {
return classes.textAreaWithoutStyle;
}
};
const checkIfDefaultValueInTextAreaAndRemooveIt = () => {
if (valueOfInput === 'Default Text') {
setValueOfInput('');
}
};
const onInputChange = (e) => {
setValueOfInput(e.target.value);
};
return (
<TextareaAutosize
maxRows={4}
className={returnStyleBasedOnInput()}
value={valueOfInput}
onChange={onInputChange}
onClick={checkIfDefaultValueInTextAreaAndRemooveIt}
/>
);
}
Edit code on Stack Blitz: https://stackblitz.com/edit/react-fnx6we-3vdn7i?file=demo.js
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);
`;
How add custom scrollbar in material ui.?
I have search many things to add such scrollbar finally i have got this.
thank you everyone.
import React from "react";
import { Box} from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
root: {
"&::-webkit-scrollbar": {
width: 7,
},
"&::-webkit-scrollbar-track": {
boxShadow: `inset 0 0 6px rgba(0, 0, 0, 0.3)`,
},
"&::-webkit-scrollbar-thumb": {
backgroundColor: "darkgrey",
outline: `1px solid slategrey`,
},
},
}));
export default const Customscroll= (props) => {
const classes = useStyles();
return (
<Box className={classes.root}>
</Box>
);
};