I am new to react and recharts and wanted to show tooltip for individual bars but Unfortunately It shows tooltip for the first bar not for the others.
Here is my code
import React, { memo } from "react";
import {
Bar,
BarChart,
CartesianGrid,
LabelList,
Rectangle,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
} from "recharts";
import { makeStyles } from "#material-ui/core/styles";
import ChartWrapper from "../chartParent/chartWrapper/ChartWrapper";
import CustomTooltip from "../timeSeriesChart/CustomTooltip";
const Categories = [
{ category: "great", fill: "#00D063" },
{ category: "fair", fill: "#FFC135" },
{ category: "risky", fill: "#F44138" },
];
const useStyles = makeStyles((theme) => ({
root: {
margin: -30,
width: 160,
backgroundColor: "#fff",
borderRadius: 5.5,
},
title: {
fontFamily: "Open Sans Condensed",
fontWeight: 600,
fontSize: 18,
},
tooltipData: {
width: "100%",
height: 31,
borderRadius: "5.5px 5.5px 0px 0px",
},
label: {
color: "#fff",
fontFamily: "Lato",
fontWeight: 400,
fontSize: 14,
marginLeft: 18,
paddingTop: "7px",
},
toolValue: {
marginTop: 11,
marginLeft: 18,
fontFamily: "Roboto",
fontWeight: 600,
fontSize: 19,
},
signature: {
fontWeight: 500,
fontSize: 14,
marginTop: -10,
marginLeft: 18,
paddingBottom: 11,
paddingRight: 18,
color: "#8D8D8D",
fontFamily: "Lato",
},
}));
const PerformanceBreakdownChart = ({ data, ...props }) => {
const classes = useStyles();
console.log("categories", data);
return (
<ChartWrapper {...props}>
<ResponsiveContainer minHeight={150} width={"100%"} height="100%">
<BarChart
data={data}
margin={{
top: 30,
right: 20,
left: 20,
bottom: 0,
}}
barSize={20}
>
<CartesianGrid horizontal={false} vertical={false} />
<XAxis dataKey="week" axisLine={false} tickLine={false} />
<YAxis hide={true} dy={4} />
<Tooltip
cursor={{ fill: "transparent" }}
content={<CustomTooltip />}
/>
{Categories.map(({ category, fill }) => (
<Bar
key={category}
dataKey={category}
fill={fill}
isAnimationActive={false}
shape={<Rectangle radius={[10, 10, 10, 10]} />}
minPointSize={16}
>
<LabelList
dataKey={category}
position="insideBottomLeft"
dy={11}
offset="15"
angle="-90"
fill="#FFF"
/>
</Bar>
))}
</BarChart>
</ResponsiveContainer>
</ChartWrapper>
);
};
export default memo(PerformanceBreakdownChart);
CustomTooltip.js
import React, { memo } from "react";
import { makeStyles } from "#material-ui/core/styles";
import { getCategory, getCategoryColor } from "../../../data/helpers/helpers";
import { useTranslation } from "react-i18next";
import { GREY } from "../../../pages/overviewPage/containers/DistanceTraveledParentContainer";
const useStyles = makeStyles((theme) => ({
root: {
margin: -30,
width: 160,
backgroundColor: "#fff",
borderRadius: 5.5,
},
title: {
fontFamily: "Open Sans Condensed",
fontWeight: 600,
fontSize: 18,
},
tooltipData: {
width: "100%",
height: 31,
borderRadius: "5.5px 5.5px 0px 0px",
},
label: {
color: "#fff",
fontFamily: "Lato",
fontWeight: 400,
fontSize: 14,
marginLeft: 18,
paddingTop: "7px",
},
toolValue: {
marginTop: 11,
marginLeft: 18,
fontFamily: "Roboto",
fontWeight: 600,
fontSize: 19,
},
signature: {
fontWeight: 500,
fontSize: 14,
marginTop: -10,
marginLeft: 18,
paddingBottom: 11,
paddingRight: 18,
color: "#8D8D8D",
fontFamily: "Lato",
},
}));
const CustomTooltip = ({ active, payload, label, signature }) => {
const { t } = useTranslation();
const classes = useStyles();
if (active && payload) {
const color = signature ? GREY : getCategoryColor(payload[0].value);
const customLabel = t(
signature ? signature : getCategory(payload[0].value)
);
return (
<div className={classes.root}>
<div
className={classes.tooltipData}
style={{ backgroundColor: `${color}` }}
>
<p className={classes.label}>{`${label}`}</p>
</div>
<p className={classes.toolValue}>{payload[0].value}</p>
<p className={classes.signature}>{customLabel}</p>
</div>
);
}
return null;
};
export default memo(CustomTooltip);
The above code output looks like this.
output
How can I show tooltip for individual bars as the following snippet?
actual needed tooltip
I am trying to create a UI in react-native like in the below picture:
Until now I can do only like this:
But is there any proper way to do that?
<View style={styles.frame1}>
<View style={styles.frameBefore}></View>
<View style={styles.frame2}>
<TextInput/>
</View>
</View>
frame1: {
flexDirection: 'row',
margin: 10,
borderColor: LightColorLine,
borderStyle:'solid',
borderWidth: 0.5,
backgroundColor: LightColorBackgr,
padding:10,
},
frame2:{
backgroundColor: LightColorTextBackgr,
padding: -50,
flex: 0.98,
},
frameBefore:{
width: 0,
height: 60,
borderRightWidth: 0.9,
borderColor: LightColorLine,
borderStyle:'solid',
shadowColor: '#000000',
shadowOffset: {
width: 0,
height: 10,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
flex: 0.01,
transform: [{
rotate: '45deg'
}]
},
Here is the closest I was able to get
The tricky part was creating the shadow on an angle, especially considering the API's React-Native provide for shadows differ so much between iOS and Android.
To overcome this I used a linear gradient which is not included by React Native by default. I used expo-linear-gradient but there a few others you can use if you would prefer.
export const Triangle = props => (
<View style={props.style}>
<LinearGradient
colors={['black', 'transparent']}
start={[0, 0]}
end={[0.5, 0.5]}
style={styles.triangleShadow}
/>
<View style={styles.triangle} />
</View>
);
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.card}>
<Text style={styles.text}>Be Cool.</Text>
<Triangle style={styles.topLeftTriangle} />
<Triangle style={styles.bottomRightTriangle} />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 32,
},
text: {
fontSize: 18,
padding: 32,
paddingVertical: 48,
fontWeight: 'bold',
borderWidth: 1,
backgroundColor: '#F66F6F',
color: 'white',
borderColor: 'gray',
},
card: {
borderWidth: 1,
padding: 8,
borderColor: 'gray',
},
triangle: {
width: 0,
height: 0,
backgroundColor: 'transparent',
borderStyle: 'solid',
borderRightWidth: 80,
borderTopWidth: 80,
borderRightColor: 'transparent',
borderTopColor: '#ecf0f1',
},
triangleShadow: {
height: 90,
width: 90,
position: 'absolute',
top: 0,
left: 0,
},
topLeftTriangle: {
position: 'absolute',
top: -10,
left: -10,
},
bottomRightTriangle: {
position: 'absolute',
bottom: -10,
right: -10,
transform: [{ rotate: '180deg' }],
},
});
I am building a wordpress app using react native
I've used in the load of the app `import {I18nManager} from 'react-native';
I18nManager.forceRTL(true);`
to force the app to use RTL, it worked for me but in the postdetails it still showing LTR even after using
flexDirection: Constants.RTL ? 'row-reverse' : 'row' -> (for the label text)
here is my code for postdetails styles.js, please help me finding the solution for this issue
/** #format */
import { StyleSheet, Dimensions } from 'react-native'
import { Constants } from '#common'
const { width, height } = Dimensions.get('window')
const vw = width / 100
const vh = height / 100
export default StyleSheet.create({
body: {
flex: 1,
backgroundColor: '#fff',
width,
},
fill: {
flex: 1,
backgroundColor: '#ffffff',
},
card: {
width,
flexDirection: Constants.RTL ? 'row-reverse' : 'row',
},
box: {
width: vw * 40,
height: 100,
backgroundColor: '#ccc',
marginLeft: 20,
marginTop: 10,
marginBottom: 10,
},
header: {
position: 'absolute',
top: 0,
left: 0,
zIndex: 2,
right: 0,
backgroundColor: 'rgba(255, 255, 255, 0.5)',
overflow: 'hidden',
height: Constants.Window.headerHeight,
},
linearGradient: {
height: 50,
zIndex: 3,
width,
alignItems: 'flex-end',
justifyContent: 'flex-end',
position: 'absolute',
},
linearGradientBottom: {
height: 50,
bottom: 0,
zIndex: 3,
width,
alignItems: 'flex-end',
justifyContent: 'flex-end',
position: 'absolute',
},
headerIcon: {
height: 40,
position: 'absolute',
top: 0,
width,
zIndex: 4,
},
image: {
width: vw * 40,
height: 90,
resizeMode: 'cover',
marginLeft: 8,
marginTop: 20,
marginBottom: 10,
},
content: {
width: vw * 50,
marginLeft: 14,
marginTop: 20,
marginBottom: 30,
},
greyRow: {
backgroundColor: '#eee',
},
menuView: {
backgroundColor: '#F4F4F4',
height: 40,
},
menuItemView: {
marginTop: 6,
marginRight: 6,
marginBottom: 6,
marginLeft: 6,
height: 28,
},
menuItem: {
marginTop: 6,
marginRight: 16,
marginBottom: 6,
marginLeft: 16,
fontSize: 12,
fontWeight: '500',
color: '#8A939C',
},
menuItemActive: {
backgroundColor: '#fff',
borderRadius: 16,
borderWidth: 1,
borderColor: '#eee',
},
menuActiveText: {
color: '#000',
},
bannerImage: {
width,
height: width / 2 + 40,
backgroundColor: 'rgba(67, 130, 208, 0.2)',
},
placeHolderImage: {
alignItems: 'center',
width,
height: width / 3,
justifyContent: 'center',
backgroundColor: 'rgba(67, 130, 208, 0.2)',
},
backgroundOne: {
backgroundColor: 'rgba(58, 75, 133, 0.6)',
},
backgroundTwo: {
backgroundColor: 'rgba(188, 59, 36, 0.6)',
},
backgroundThree: {
backgroundColor: 'rgba(57, 174, 84, 0.6)',
},
bannerText: {
position: 'absolute',
bottom: 30,
backgroundColor: 'rgba(0, 0, 0, 0.3)',
width: vw * 60,
},
bannerTitle: {
marginTop: 12,
marginRight: 12,
marginBottom: 2,
marginLeft: 12,
color: 'white',
fontSize: 15,
},
bannerDate: {
color: 'rgba(255, 255, 255, 0.7)',
fontSize: 9,
fontWeight: '500',
marginLeft: 12,
marginBottom: 12,
},
time: {
color: '#999',
fontSize: 12,
marginTop: 0,
marginBottom: 0,
marginLeft: 0,
},
tagView: {
flexDirection: Constants.RTL ? 'row-reverse' : 'row',
alignItems: 'flex-start',
justifyContent: 'flex-start',
marginBottom: 6,
},
tag: {
backgroundColor: '#aaa',
borderRadius: 12,
alignSelf: 'flex-end',
marginRight: 4,
},
tagText: {
fontSize: 9,
marginTop: 1,
marginRight: 8,
marginBottom: 1,
marginLeft: 8,
color: 'white',
fontWeight: '600',
},
hlist: {
flex: 1,
backgroundColor: 'white',
paddingTop: 0,
paddingRight: 0,
paddingBottom: 0,
paddingLeft: 0,
},
color: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: '#EBEBEB',
},
title: {
color: '#333',
fontSize: 22,
textAlign: 'center',
fontWeight: '200',
marginTop: 12,
},
titleSmall: {
fontSize: 13,
color: '#999',
textAlign: 'center',
marginBottom: 10,
marginTop: 4,
},
productItem: {
width: width - 30,
height: 400,
marginTop: 5,
marginRight: 5,
marginBottom: 5,
marginLeft: 5,
},
detailBlock: {
alignItems: 'center',
backgroundColor: '#fff',
paddingTop: 20,
paddingRight: 20,
paddingBottom: 20,
paddingLeft: 20,
width,
},
scrollView: {
backgroundColor: '#fff',
paddingTop: Constants.Window.headerHeight,
paddingBottom: 200,
},
scrollViewContent: {
position: 'relative',
zIndex: 9,
paddingBottom: 200,
},
innerContent: {
backgroundColor: '#fff'
},
detailDesc: {
color: '#333',
width: width - 20,
marginTop: 16,
marginRight: 16,
marginBottom: 2,
marginLeft: 13,
fontWeight: '500',
fontSize: 22,
textAlign: Constants.RTL ? 'right' : 'left',
},
largeImage: {
width,
height: width - 120,
resizeMode: 'cover',
},
largeContent: {
width,
position: 'absolute',
bottom: 0,
height: 100,
},
largeTitle: {
color: '#fff',
fontSize: 18,
paddingTop: 20,
paddingRight: 20,
paddingBottom: 0,
paddingLeft: 20,
},
description: {
backgroundColor: '#fff',
flexDirection: Constants.RTL ? 'row-reverse' : 'row',
},
imageBackGround: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
width,
height: Constants.Window.headerHeight
},
detailPanel: {
height: 380,
width,
alignItems: 'center',
justifyContent: 'flex-end',
},
toolbar: {
backgroundColor: 'black',
},
shareIcon: {
flexDirection: Constants.RTL ? 'row-reverse' : 'row',
width: 100,
position: 'absolute',
right: 0,
bottom: 16,
},
newsIcons: {
color: '#999',
marginLeft: 20,
},
newsTitle: {
fontSize: 18,
marginTop: 20,
marginRight: 20,
marginBottom: 20,
marginLeft: 20,
color: 'white',
fontWeight: '400',
textAlign: 'left',
backgroundColor: 'transparent',
},
avatar: {
width: 32,
height: 32,
borderRadius: 20,
resizeMode: 'cover',
marginTop: 12,
marginRight: 12,
marginBottom: 12,
marginLeft: 12,
},
wrapComment: {
paddingLeft: 15,
paddingRight: 15,
backgroundColor: '#F7F7F7',
flex: 2 / 6,
},
headCommentText: {
fontSize: 20,
fontWeight: '600',
},
titleVideo: {
flex: 1 / 6,
paddingLeft: 15,
paddingRight: 12,
},
titleVideoText: {
fontSize: 18,
color: 'rgb(11,6,6)',
lineHeight: 22,
fontWeight: 'bold',
},
countViews: {
flex: 1 / 6,
marginTop: 15,
marginLeft: 15,
marginBottom: 5,
},
countViewsText: {
fontSize: 18,
lineHeight: 18,
color: 'rgb(149,149,149)',
},
wrapLikeShare: {
flex: 1 / 6,
marginTop: 5,
marginRight: 10,
marginBottom: 5,
flexDirection: Constants.RTL ? 'row-reverse' : 'row',
justifyContent: 'flex-end',
},
wrapLikeShareInner: {
flexDirection: Constants.RTL ? 'row-reverse' : 'row',
},
icon: {
flexDirection: Constants.RTL ? 'row-reverse' : 'row',
marginRight: 10,
},
numberIcon: {
marginLeft: 5,
fontSize: 18,
},
author: {
color: '#999',
fontSize: 13,
fontWeight: '600',
marginTop: 12,
marginRight: 12,
marginBottom: 12,
marginLeft: 12,
textAlign: Constants.RTL ? 'right' : 'left',
},
relatedPostText: {
fontSize: 16,
fontWeight: 'bold',
paddingTop: 10,
paddingRight: 10,
paddingBottom: 10,
paddingLeft: 10,
},
shareIcons: {
flexDirection: Constants.RTL ? 'row-reverse' : 'row',
justifyContent: 'flex-end',
position: 'absolute',
width,
right: 4,
top: 8,
zIndex: 10,
},
videoView: {
backgroundColor: 'rgba(0,0,0, .8)',
flex: 1,
},
video: {
height: vh * 45,
width,
backgroundColor: '#000',
},
spinkitView: {
backgroundColor: '#ffffff',
flex: 1,
height,
justifyContent: 'center',
position: 'absolute',
top: 0,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
})
You need to reload the app after forceRTL.Check this link enter link description here
But I think this not a good solution.
I'm trying to initialize a Text component in a parent component with a certain state, but it's not showing up at all. This should be something really simple and something I've done multiple times before, what am I doing wrong here? Nothing is showing up in the text component. Here is the component code:
import React from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';
export class GeneralInput extends React.Component {
constructor(props) {
super(props);
this.state = {
placeholder: this.props.placeholder,
inputValue: "",
inputting: false,
validationMessage: "This is a required field",
validationStyles: styles.noValidation,
};
}
whenInputIsFocused() {
this.setState({placeholder: ""});
}
whenInputIsBlurred() {
this.setState({validationMessage: "This field is required"});
/* if (this.state.inputValue === "") {
this.setState({placeholder: this.props.placeholder});
}*/
}
storeValue = (inputValue) => {
this.setState({inputValue});
this.props.onChange({key: this.props.fieldId, value: inputValue});
}
focusNextField(nextField) { this.refs[nextField].focus(); }
render() {
const autoFocus = this.props.autoFocus == 'true';
const multiline = this.props.multiline == 'true';
return(
<View style={styles.outerContainer}>
<Text style={styles.labelText}>{this.props.labelText}</Text>
<View style={styles.inputContainer}>
<TextInput
autoCapitalize='none'
autoFocus={this.props.autoFocus}
onChangeText={this.storeValue}
value={this.state.inputValue}
secureTextEntry={this.props.secureTextEntry}
onBlur={this.whenInputIsBlurred.bind(this)}
onFocus={this.whenInputIsFocused.bind(this)}
underlineColorAndroid="transparent"
keyboardType={this.props.type}
returnKeyType={this.props.returnKeyType}
placeholder={this.state.placeholder}
placeholderTextColor='rgba(255, 255, 255, 0.3)'
multiline={multiline}
selectTextOnFocus={false}
onSubmitEditing={() => {this.focusNextField(this.props.ref)}}
blurOnSubmit={(this.props.moveAlongType === 'next') ? false : true}
style={styles.inputStyles} />
<Text style={styles.validationText}>{this.state.validationMessage}</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
outerContainer: {
justifyContent: 'center',
alignItems: 'flex-start',
width: '90%',
marginBottom: 20,
},
labelText: {
fontFamily: 'rubik-bold',
fontSize: 14,
fontWeight: 'bold',
color: '#fff',
marginBottom: 5,
},
inputContainer: {
height: 40,
width: '100%',
backgroundColor: 'rgba(255, 255, 255, 0.3);',
shadowColor: 'rgba(0, 0, 0, 0.15)',
shadowOffset: {width: 0,height: 2},
shadowOpacity: 0,
shadowRadius: 0,
borderRadius: 2,
},
inputStyles: {
height: '100%',
width: '100%',
fontSize: 14,
color: '#fff',
paddingLeft: 15,
fontFamily: 'rubik-bold',
},
validationText: {
color: '#e16e17',
fontSize: 12,
fontFamily: 'rubik-bold',
marginTop: 3,
display: 'none',
},
});
Assuming you mean this
<Text style={styles.validationText}>{this.state.validationMessage}</Text>
Your styles have
validationText: {
color: '#e16e17',
fontSize: 12,
fontFamily: 'rubik-bold',
marginTop: 3,
display: 'none',
},
The display:'none' is going to make it not show up
I tried your code and modified the backgroundColor for the text area.
labelText: {
backgroundColor: "red",
...
I get this, which I believe is what you are looking for:
Are you showing the text on a white background?