Material UI Slider won't slide - javascript

I have a Material UI slider that won't slide when you click on it and drag it. I've more or less copied one of the examples from https://material-ui.com/components/slider/ and added an onChange function. The values update just fine if you click around to different spots. I've been staring at this too long and have gone code blind and can't figure out what I'm missing.
Here's a link to a Sandbox
import React, { useState } from "react";
import PropTypes from "prop-types";
import withStyles from "#material-ui/styles/withStyles";
import Card from "#material-ui/core/Card";
import { Typography, Paper, Grid, CssBaseline } from "#material-ui/core";
import Slider from "#material-ui/core/Slider";
function App(props) {
const [state, setState] = useState({
fields: {
contractAmount: 10000,
termValue: 2
}
});
const handleInvestmentChange = name => (e, value) => {
setState({
...state,
fields: {
...state.fields,
[name]: value
}
});
};
const AmountSlider = withStyles({
root: {
color: "#52af77",
height: 8
},
thumb: {
height: 24,
width: 24,
backgroundColor: "#fff",
border: "2px solid currentColor",
marginTop: -8,
marginLeft: -12,
"&:focus,&:hover,&$active": {
boxShadow: "inherit"
}
},
active: {},
valueLabel: {
left: "calc(-50% + 14px)",
top: -22,
"& *": {
background: "transparent",
color: "#000"
}
},
track: {
height: 8,
borderRadius: 4
},
rail: {
height: 8,
borderRadius: 4
}
})(Slider);
const TermSlider = withStyles({
root: {
color: "#52af77",
height: 8
},
thumb: {
height: 24,
width: 24,
backgroundColor: "#fff",
border: "2px solid currentColor",
marginTop: -8,
marginLeft: -12,
"&:focus,&:hover,&$active": {
boxShadow: "inherit"
}
},
active: {},
valueLabel: {
left: "calc(-50% + 4px)"
},
track: {
height: 8,
borderRadius: 4
},
rail: {
height: 8,
borderRadius: 4
}
})(Slider);
return (
<div>
<CssBaseline />
<Typography variant="h4" align="center" component="h1" gutterBottom>
Select your Investment Level
</Typography>
<Card>
<Paper style={{ padding: 16, minHeight: 445, maxHeight: 445 }}>
<Grid container alignItems="flex-start" spacing={2}>
<Grid item xs={12} lg={12} xl={12}>
<Typography variant="h4">Investment Amount</Typography>
<Typography variant="h6" gutterBottom>
${state.fields.contractAmount.toLocaleString()}
</Typography>
<AmountSlider
valueLabelDisplay="auto"
defaultValue={10000}
value={
typeof state.fields.contractAmount === "number"
? state.fields.contractAmount
: 2000
}
onChange={handleInvestmentChange("contractAmount")}
step={1000}
min={2000}
max={100000}
/>
<Typography variant="h4">Investment Term</Typography>
<Typography variant="h6" gutterBottom>
{state.fields.termValue} years
</Typography>
<TermSlider
name="termValue"
valueLabelDisplay="off"
aria-label="term slider"
defaultValue={10}
value={
typeof state.fields.termValue === "number"
? state.fields.termValue
: 2
}
onChange={handleInvestmentChange("termValue")}
min={2}
max={25}
/>
<Grid
item
style={{
marginTop: 16,
alignContent: "right",
alignItems: "right"
}}
>
<Typography variant="p">
*Your investment amount and contract length can be changed at
any time as described in our Terms & Conditions.
</Typography>
</Grid>
</Grid>
</Grid>
</Paper>
</Card>
</div>
);
}
export default App;

If you need to customize the theme of MUI Slider then you need to use MUI Theme Provider.
And you need to import it like,
import { ThemeProvider, createMuiTheme } from "#material-ui/styles";
Then try moving your custom css into a variable with the value of createMuiTheme method which has overrides property like,
const AmountSlider = createMuiTheme({
overrides: {
MuiSlider: {
root: {
color: "#52af77",
height: 8
},
thumb: {
height: 24,
width: 24,
backgroundColor: "#fff",
border: "2px solid currentColor",
marginTop: -8,
marginLeft: -12,
"&:focus,&:hover,&$active": {
boxShadow: "inherit"
}
},
active: {},
valueLabel: {
left: "calc(-50% + 14px)",
top: -22,
"& *": {
background: "transparent",
color: "#000"
}
},
track: {
height: 8,
borderRadius: 4
},
rail: {
height: 8,
borderRadius: 4
}
}
}
});
Then in template use it like,
<ThemeProvider theme={AmountSlider}>
<Slider
valueLabelDisplay="off"
defaultValue={10000}
value={
typeof state.fields.contractAmount === "number"
? state.fields.contractAmount
: 2000
}
onChange={handleInvestmentChange("contractAmount")}
step={1000}
min={2000}
max={100000}
/>
</ThemeProvider>
Same way you can implement the custom theme for TermSlider as well..
Forked Codesandbox
Note:
I think you are using the same css for both AmountSlider and TermSlider if so, create a single theme variable and use it for both..
Eg.., You could use theme={AmountSlider} for both the Amount and Term sliders if both has the same css.. Ofcourse the variable name can be unique in this case..

Related

How we can give auto height to FlatList based on its list items content in React Native

I am using FlatList in my component which is working fine. All is wanted is that my entire screen should have an automatic height to it and FlatList contents never does out of the screen height.
Also, the height of FlatList should be changed based on content/items in it rather than giving any fixed height.
How I can be acheived both cases like automatic screen height and auto height of FlatList content?
Code:
import React, { useState, useEffect } from 'react';
import {
View,
StyleSheet,
useWindowDimensions,
Text,
FlatList,
SafeAreaView,
TouchableOpacity,
} from 'react-native';
import { LinearGradient as LinearGradientView } from 'expo-linear-gradient';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { ActivityIndicator, ThemeProvider } from 'react-native-paper';
import { ScrollView } from 'react-native-gesture-handler';
import { useIsFocused, useNavigation } from '#react-navigation/native';
import Svg, { Path } from 'react-native-svg';
import { BASE_GRADIENT_HEAVY } from '../rooms/Background';
import { useResolution } from '../browse/useResolution';
import { OnboardingNavigationProp } from '../navigation/LinkingConfiguration';
import { LIGHT_THEME } from '../Theme';
import { OnboardingBack } from './OnboardingBack';
import {
useOnboardingYearsOfExperiencePage,
useOnboardingYearsOfExperienceSubmit,
} from './useOnboardingYearsOfExperiencePage';
export function OnboardingYearsOfExperience({ route }: { route?: any }) {
const { height } = useWindowDimensions();
const { top: safeAreaTop } = useSafeAreaInsets();
const [selectedId, setSelectedId] = useState<{ id: string }>();
const [role_id, setRoleId] = useState<number>();
const { navigate } =
useNavigation<OnboardingNavigationProp<'OnboardingConfirmAllDetails'>>();
const parentUrl = route?.params.result.onboarding._links;
const initialUrl = parentUrl.onboarding_years_of_experience.href;
const onboardingUrl = parentUrl.self.href;
useEffect(() => {
setRoleId(route?.params.role_id);
}, []);
const isFocused = useIsFocused();
const { contentType } = useResolution();
const {
data: result,
isLoading,
error,
} = useOnboardingYearsOfExperiencePage(initialUrl, contentType, role_id, {
enabled: isFocused,
notifyOnChangeProps: ['data', 'isLoading', 'error'],
});
const {
mutateAsync: updateYearsOfExperience,
isLoading: isUpdatingYearsOfExperience,
error: yearsOfExperienceUpdateError,
} = useOnboardingYearsOfExperienceSubmit(onboardingUrl);
const Arrow = ({ style }: { style: object }) => {
return (
<Svg width="7" height="11" viewBox="0 0 7 11" fill="none" style={style}>
<Path
d="M6.28711 5.53931C6.28711 5.31649 6.19783 5.12476 6.02452 4.95376L1.9911 1.07251C1.85455 0.937781 1.68649 0.865234 1.48692 0.865234C1.07728 0.865234 0.751664 1.18651 0.751664 1.58552C0.751664 1.78243 0.830441 1.96898 0.977493 2.11407L4.54875 5.53413L0.977492 8.95937C0.835692 9.10446 0.751663 9.28583 0.751662 9.48792C0.751662 9.88693 1.07728 10.2082 1.48692 10.2082C1.68649 10.2082 1.85455 10.1357 1.99635 10.0009L6.02452 6.11968C6.20308 5.93832 6.28711 5.75695 6.28711 5.53931Z"
fill="#4D4D4D"
/>
</Svg>
);
};
const Item = ({
item,
onPress,
}: {
item?: { id: string; title: string };
onPress: () => void;
}) => (
<TouchableOpacity onPress={onPress}>
<Text
style={{
color: '#4D4D4D',
fontFamily: 'Inter_400Regular',
fontStyle: 'normal',
fontWeight: '400',
fontSize: 16,
lineHeight: 32,
padding: 3,
margin: 2,
}}
>
{item?.title}
</Text>
</TouchableOpacity>
);
const renderItem = ({ item }: { item: { id: string; title: string } }) => {
return (
<React.Fragment>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
borderRadius: 5,
backgroundColor:
selectedId?.id === item?.id ? '#F2F2F2' : 'transparent',
}}
>
<View style={{ width: '90%' }}>
<Item
item={item}
onPress={() => {
setSelectedId({ id: item.id });
updateYearsOfExperience({ id: item.id, role_id })
.then((result) => {
navigate('Onboarding', {
screen: 'OnboardingConfirmAllDetails',
params: { result },
});
})
.catch(() => {});
}}
/>
</View>
<View style={{ width: '10%' }}>
<Arrow style={{ position: 'absolute', top: 16, right: 10 }} />
</View>
</View>
</React.Fragment>
);
};
return (
<ThemeProvider theme={LIGHT_THEME}>
<View style={{ height: safeAreaTop }} />
<View style={styles.topHeader}>
<LinearGradientView
{...BASE_GRADIENT_HEAVY}
style={[styles.gradiantStyle]}
/>
</View>
<View style={styles.innerContainer}>
<ScrollView
contentContainerStyle={{
marginHorizontal: 'auto',
alignSelf: 'center',
width: '100%',
backgroundColor: '#ffffff',
height: '100%',
}}
>
<OnboardingBack
style={{
left: -10,
}}
/>
<Text style={styles.topHeadline}>
How many years of experience do you have?
</Text>
<Text style={styles.middleHeadline}>
Jump-start the conversation by sharing your years of experience
within healthcare.
</Text>
{isLoading || isUpdatingYearsOfExperience ? (
<ActivityIndicator size="large" />
) : (
<SafeAreaView>
<FlatList
contentContainerStyle={{ flexGrow: 1 }}
data={Object.values(
result!['years_of_experiences']['years_of_experiences_list']
)}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
style={{
borderWidth: 1,
borderStyle: 'solid',
borderColor: '#D7D7D7',
borderRadius: 5,
padding: 12,
height: '27%',
}}
ListEmptyComponent={
<View>
<Text>No data found</Text>
</View>
}
/>
</SafeAreaView>
)}
</ScrollView>
</View>
</ThemeProvider>
);
}
const styles = StyleSheet.create({
innerContainer: {
display: 'flex',
position: 'relative',
backgroundColor: 'white',
padding: 18,
},
topHeader: {
backgroundColor: '#e5dede',
padding: 0,
width: '100%',
},
topHeadline: {
fontSize: 24,
fontFamily: 'CircularStd_Medium',
fontStyle: 'normal',
fontWeight: '500',
color: '#222222',
marginTop: 40.6,
marginBottom: 14.6,
display: 'flex',
alignItems: 'center',
lineHeight: 32,
},
middleHeadline: {
fontSize: 16,
fontFamily: 'Inter_400Regular',
fontStyle: 'normal',
fontWeight: '400',
lineHeight: 24,
color: '#4D4D4D',
marginBottom: 30,
},
gradiantStyle: {
width: 248.4,
height: 4.71,
},
});
add the following style to your flatList =>
style={{maxHeight:'what ever you want',flexGrow:0}}

Material-UI: The key `paperFullWidth` provided to the classes prop is not implemented in WithStyles(ForwardRef(Dialog))

Material-UI: The key paperFullWidth provided to the classes prop is not implemented in WithStyles(ForwardRef(Dialog)).
You can only override one of the following: root.
<Dialog
classes={{
paperFullWidth: props.classes.dialogCustomizedWidth,
paper: props.classes.dialogPaper,
}}
transitionDuration={{ enter: 0, exit: 0 }}
fullWidth={true}
maxWidth={false}
aria-labelledby="customized-dialog-title"
></Dialog>
You can't use withStyles and styles differently from the element to manipulate the dialog element.
For example, incorrect usage:
const styles = (theme) => ({
dialogPaper: {
height: "95%",
padding: 0,
margin: 0,
},
dialogCustomizedWidth: {
"max-width": "70%",
"max-heigth": "95%",
},
root: {
margin: 0,
backgroundColor: theme.palette.dialogCustom.titleBg,
},
closeButton: {
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.dialogCustom.titleIconColor,
padding: 3,
},
titleTypography: {
color: theme.palette.dialogCustom.titleTextColor,
},
});
const Dialog = withStyles((theme) => ({
root: {
margin: 10,
},
}))(MuiDialog);
function dialog(props) {
return (
<Dialog
classes={{
paperFullWidth: props.classes.dialogCustomizedWidth,
paper: props.classes.dialogPaper,
}}
transitionDuration={{ enter: 0, exit: 0 }}
fullWidth={true}
maxWidth={false}
aria-labelledby="customized-dialog-title"
open={props.visible}
onClose={() => {
props.close();
}}
>
<DialogTitle
id="customized-dialog-title"
onClose={() => {
props.close();
}}
>
{props.title}
</DialogTitle>
<DialogContent
dividers
style={{ overflowX: "hidden", margin: 0, padding: 0 }}
>
{props.children}
</DialogContent>
</Dialog>
);
}
export default withStyles(styles)(dialog);

how to dynamically control the indicatorStyle react navigation 5x

I have 4 screens, then I used the Style indicator to get a white border. However my border on the outros screen is too big and the restaurantes screen is small. How can I put a different width of the Style indicator for each screen? I'm using react navigation 5x Look how it is https://i.stack.imgur.com/9D5UW.png
https://i.stack.imgur.com/eVgHi.png
My code
import React from 'react';
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
import Restaurantes from '../pages/Restaurantes';
import Mercados from '../pages/Mercados';
import Farmácias from '../pages/Farmácias';
import Outros from '../pages/Outros';
const Tab = createMaterialTopTabNavigator();
export default function Routes() {
return (
<>
<Tab.Navigator
tabBarOptions={{
allowFontScaling: false,
activeTintColor: '#111',
inactiveTintColor: '#a8a8a8',
indicatorStyle: {
height: 23,
width: 80,
position: 'absolute',
left: '3%',
marginBottom: 12,
borderRadius: 15,
marginLeft: 5,
backgroundColor: '#fff',
},
tabStyle: {
marginLeft: 10,
paddingLeft: 20,
},
labelStyle: {
fontSize: 12,
width: 100,
},
style: {
backgroundColor: '#5f12b8',
},
}}
>
<Tab.Screen name="restaurantes" component={Restaurantes} />
<Tab.Screen name="mercados" component={Mercados} />
<Tab.Screen name="farmácias" component={Farmácias} />
<Tab.Screen name="outros" component={Outros} />
</Tab.Navigator>
</>
);
}
You can use 'renderIndicator'.
I will give you an example.
Copy paste the below code inside your 'tabBarOptions'
renderIndicator: (route) => {
if (!route.getTabWidth()) {
return null;
}
return (
<View style={{
width: route.getTabWidth(),
height: '100%',
left: route.navigationState.index * route.getTabWidth(),
backgroundColor: 'orange',
alignItems: 'center',
justifyContent: 'center',
}}>
<View style={{
position: 'absolute',
width: '80%',
backgroundColor: '#fff',
borderRadius: 15,
height: 20,
}}></View>
</View>
)},
}}
This should fix your issue. Some simple tweaking is necessary. If you need more help. Please do ask.
I will link the docs for you as well.
https://reactnavigation.org/docs/material-top-tab-navigator/#tabbaroptions

Rotate label - Material UI button

I've got a button like this (material-ui):
//theme.js
export const XButtonTop = withStyles({
root: {
borderColor: medium_col,
borderRadius: 1,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
height: 28
},
label: {
textTransform: "uppercase",
fontSize: "10px"
}
})(Button);
//App.js
import {
XButtonTop
} from "../theme";
const Selector = state => {
return (
<div>
<XButtonTop fullWidth size="small" disableElevation>
)
</XButtonTop>
</div>
)
}
I need to rotate the label (90 degrees).
Can someone help me please? Thanks
label: {
textTransform: 'capitalize',
transform: 'rotate(-90deg)',
}
Then you may want to change the height of the button too. Something like this for the root:
height: 120,
width: 30

How to add State to a Function from Material-UI

So I have a layout from Material UI. The function name is called MainMenu. It's in function form, but I want to add states to it. How do I do that? I tried converting it to class, but I don't know how material-ui works....I have deleted some of the code, to cut down on unnecessary bits.
const styles = theme => ({
appBar: {
position: 'relative',
},
icon: {
marginRight: theme.spacing.unit * 2,
},
heroUnit: {
backgroundColor: '#fff',
},
heroUnits: {
backgroundColor: '#fff',
},
heroContent: {
backgroundColor: '#fff',
maxWidth: 600,
margin: '0 auto',
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`,
},
heroButtons: {
marginTop: theme.spacing.unit * 4,
},
layout: {
backgroundColor: '#fff',
width: 'auto',
marginLeft: theme.spacing.unit * 3,
marginRight: theme.spacing.unit * 3,
[theme.breakpoints.up(1100 + theme.spacing.unit * 3 * 2)]: {
width: 1100,
marginLeft: 'auto',
marginRight: 'auto',
},
},
cardGrid: {
padding: `${theme.spacing.unit * 8}px 0`,
},
card: {
height: '100%',
display: 'flex',
flexDirection: 'column',
},
cardMedia: {
paddingTop: '56.25%', // 16:9
},
cardContent: {
flexGrow: 1,
},
footer: {
backgroundColor: '#fff',
padding: theme.spacing.unit * 6,
},
});
function MainMenu(props) {
const { classes } = props;
return (
<React.Fragment>
<CssBaseline />
<div className={classes.heroUnits}>
<AppBar position="static" className={classes.appBar}>
<Toolbar>
<Typography variant="h6" color="inherit" noWrap>
Dashboard
</Typography>
</Toolbar>
</AppBar>
<main>
<div className={classes.heroUnit}>
<div className={classes.heroContent}>
<Typography component="h1" variant="h2" align="center" color="textPrimary" gutterBottom>
Synapse
</Typography>
</div>
</div>
<div className={classNames(classes.layout, classes.cardGrid)}>
</div>
</main>
</div>
</React.Fragment>
);
}
MainMenu.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(MainMenu);
Deleted some code for better readability, this is how you do conditional rendering in React.
class MainMenu extends React.Component {
state = { shouldIRender: false}
const { classes } = this.props;
return (
<React.Fragment>
{this.state.shouldIRender ? <p>sure, render</p> : <p>not rendering</p>}
</React.Fragment>
);
}

Categories