Victory Charts with multiple lines and tooltips - css

I am making a graph which must zoom and display tooltips for each data point. In Victory's documentation there is a multi-line chart with tooltips however if you adjust the data set, the tooltips overlap. I found that VictoryPortal is a mechanism for overcoming this but it appears that even in the linked example, it is using VictoryPortal. (The tooltip's props has renderInPortal: true,)
To overcome this I created a second VictoryGroup after the Lines/Scatters which was just Scatters of all the data sets combined and gave them opacity: 0 so it looked like you were hovering the original Scatter dot. This approach works but feel like there must be a better, cleaner way that I'm missing here. I couldn't figure out how to make a snippet work with Victory so here's the code in question:
Method for rendering Lines/Scatters for individual data sets together in a group:
renderLine = (m, i) => (
this.state.s[i]
? <VictoryGroup
key={i}
color={m.color}
data={m.data}
labels={(d) => `y: ${d.y}\nx: ${d.x}`}
labelComponent={
<VictoryTooltip
cornerRadius={0}
style={{ fontSize: 10 }}
/>}
>
<VictoryLine />
<VictoryScatter size={(d, a) => a ? 8 : 3} />
</VictoryGroup>
: null
)
And my render method:
render() {
const { renderLine } = this
return (
<div style={{ width: '50vw', margin: '0 auto' }}>
<VictoryChart
height={400}
width={400}
padding={30}
containerComponent={<VictoryZoomContainer />}>
<VictoryAxis
domain={{ x: [-180, 180] }}
standalone
label={'Angle (°)'}
style={axisStyle}
crossAxis={false}
orientation={'bottom'}
axisLabelComponent={
<VictoryLabel orientation={'top'} y={'97%'} verticalAnchor={'end'} />
}
gridComponent={
<Line
style={{
...axisStyle.grid,
transform: 'translate3d(0,100%,0)'
}}
/>
}
tickCount={12}
tickLabelComponent={<VictoryLabel dy={-5} />}
/>
<VictoryAxis
dependentAxis
orientation={'left'}
label={'Discriminiation (dB)'}
axisLabelComponent={
<VictoryLabel orientation={'left'} x={15} />
}
standalone
offsetX={30}
style={axisStyle}
/>
{masterData.map((d, i) => renderLine(d, i))}
<VictoryGroup
color={'rgba(0,0,0,0)'}
data={[...dataSet, ...dataSet2, ...dataSet3, ...dataSet4]}
labels={(d) => `y: ${d.y}\nx: ${d.x}`}
labelComponent={
<VictoryTooltip
cornerRadius={0}
style={{ fontSize: 10 }}
/>}
>
<VictoryScatter size={(d, a) => a ? 8 : 3} />
</VictoryGroup>
</VictoryChart>
</div>
);
}
Any input or advice would be greatly appreciated. Thanks in advance!

I started with a similar solution but finally I had some successful results with the VoronoiContainer component and using the tooltip from there.
https://formidable.com/open-source/victory/docs/victory-voronoi-container/
You have to put a VoronoiContainer as a containerComponent in VictoryChart.
With that method the VictoryScatter is unnecessary.

Related

How can a prop value be used in an Stitches js component?

How to pass a prop value into a Stitchesjs component and use it in the component definition?
This is a common pattern in styled-components. In Stitches, however, I can't seem to find a way. Take this component for example:
const Spacer = styled('div', {
'16': {marginBottom: '$16'},
variants: {
size: {
'20': {marginBottom: '$20'}
}
}
});
Instead of creating 10 variants, I want to pass the amount trough a prop:
<Spacer size={'30px'} />
or even better:
<Spacer size={'$sizes$3'} />
How can I use this value so that the marginBottom matches whatever I give it?
Take a look at https://stitches.dev/docs/utils.
And then you can use like this:
<div css={{ mb: '$40' }} />
I was looking for this answer and tried a few different ways.
The easiest way for me turned out to be locally scoped theme-tokens.
So your styled component would look like this:
const Spacer = styled('div', {
marginBottom: '$$marginSize',
});
And then pass the locally scoped token into the css prop:
<Spacer css={{ $$marginSize: '$sizes$3' }} />
There was a discussion on Stitches Github about the possibility to pass dynamic values as property.
But the goal of stitches is to have the smallest runTime possible, so it was not implemented !
Github PR stitches
When you need to use a JSX variable in stitches that can be any value, one solution would be to use CSS variables;
All stitches elements get the css property, and you can pass new properties through it!
Styled component:
export const Box = styled('div', {
marginTop: 'var(--margin-top)',
backgroundColor: 'red',
width: '200px',
height: '200px',
})
Component:
export function Hero({props = 200 }) {
const variableExample = `${props}px`
return (
<>
<Box css={{ '--margin-top': '10px' }} />
<Box css={{ '--margin-top': '150px' }} />
<Box css={{ '--margin-top': variableExample }} />
</>
)
}
By far the best solution that has worked for me for this very problem. simplifies the code and is better to maintain later!

MUI Divider Thickness

I'm looking for a solution to increase the MUI Divider line thickness (stretching horizontal lines vertically, or stretching vertical lines horizontally).
I've read the documentation of MUI v5 at https://mui.com/api/divider/.
According to the API, there isn't an attribute to modify the Divider "Thickness".
I've tried different implementations of inline styles (specific to MUIv5):
<Divider sx={{height:"15px", fontSize:"50px", width:"50px", fontWeight:"bold", padding:"15px"}}/>
None of the mentioned attributes modified the "thickness" of the line.
I'm looking for a solution specific to MUI v5 Divider component. I don't want to create a Box component then implement inline sx attributes or custom classes for that Box component.
Anybody have any ideas?
You can change the CSS property border-bottom-width to modify the thiccness of the Divider:
<Divider sx={{ borderBottomWidth: 5 }} />
For vertical Divider:
<Divider orientation="vertical" flexItem sx={{ borderRightWidth: 5 }} />
styled() can also be used to create an enhanced version of Divider that supports a custom thiccness:
const MyDivider = styled(Divider)(({ thiccness, orientation }) => ({
...(thiccness !== undefined &&
(orientation === "vertical"
? { borderRightWidth: thiccness }
: { borderBottomWidth: thiccness }))
}));
<MyDivider thiccness={10} />
<MyDivider orientation="vertical" flexItem thiccness={10} />
Thats a real thicc boi
<Divider sx={{ borderBottomWidth: '45px' }} />

How to create a button with gradient color and an icon in React Native?

Like the title says, I want to ask if there's a way to create a button with gradient color and an icon in React Native? I know that gradient color can't be added without an external library, so I tried this one:
https://www.npmjs.com/package/react-native-gradient-buttons
However, I can't see a way to add Icon as a props to the gradient buttons of this library. The answer doesn't have to use the library, I would just like to know a convenient way to achieve the button I described. Thanks.
You can create your own button with an icon like below
import { Ionicons } from '#expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
const GradientButton = ({ onPress, style, colors, text, renderIcon }) => {
return (
<TouchableOpacity onPress={onPress}>
<LinearGradient colors={colors} style={style}>
{renderIcon()}
<Text style={styles.text}>{text}</Text>
</LinearGradient>
</TouchableOpacity>
);
};
Usage would be
<GradientButton
onPress={() => alert('Button Pressed')}
style={{
padding: 15,
alignItems: 'center',
borderRadius: 5,
flexDirection: 'row',
}}
colors={['#874f00', '#f5ba57']}
text="Press"
renderIcon={() => (
<Ionicons
name="md-checkmark-circle"
size={20}
color="green"
style={{ marginHorizontal: 20 }}
/>
)}
/>
You will have more control over the button and change it anyway you want, you can add more props to customize it the way you want.
You can try out the demo here
https://snack.expo.io/#guruparan/gradientbutton
The above icon and gradient packages are for expo
You can use RN Vector icons and Linear gradient package as well
In the docs of the package you provided it shows an example like this:
<GradientButton
style={{ marginVertical: 8 }}
textStyle={{ fontSize: 20 }}
gradientBegin="#874f00"
gradientEnd="#f5ba57"
gradientDirection="diagonal"
height={60}
width={300}
radius={15}
impact
impactStyle='Light'
onPressAction={() => alert('You pressed me!')}
>
Gradient Button #2
</GradientButton>
Maybe try adding your icon in between the tags instead of as prop?

How can I imitate the look of the outline and label from Material-UI's outlined textfield?

I'm trying to imitate the outlined textfield from Material-UI but I don't know how to hide the border behind the title text.
In the below image, notice how the "Due Date/Time" is taken from the Material-UI library and the title hides the border behind it but when I tried to imitate it with a custom component I just couldn't hide the border.
Alternatively, Is there a better way to use this outline design instead of just implementing it with CSS?
My current component looks liks this:
<div style={inputContainerStyle}>
<div style={{
...titleStyle,
transform: 'translate(-43px, -11px) scale(0.75)',
fontSize: '17px',
color: 'rgba(0, 0, 0, 0.54)',
position: 'absolute',
}}
>
Color
</div>
<div
className="flex-row"
style={{
border: '1px solid rgba(0, 0, 0, 0.23)',
padding: '18.5px 14px',
borderRadius: '4px',
}}
>
{
availableColors.map(color => <div style={colorCircleStyle(color)} />)
}
</div>
</div>
UPDATE
For many scenarios, my later answer (which avoids using TextField and therefore has no side-effects on FormControl context) may be more appropriate: How can I set an static outlined div similar to Material-UI's outlined textfield?
There is a great deal of flexibility in what you can do with TextField. TextField supports plugging in different types of inputs (e.g. Select, input, custom pickers) via the inputComponent property. You could leverage this to put anything inside its labelled outline by creating a custom component like this OutlinedDiv:
import React from "react";
import TextField from "#material-ui/core/TextField";
const InputComponent = ({ inputRef, ...other }) => <div {...other} />;
const OutlinedDiv = ({ children, label }) => {
return (
<TextField
variant="outlined"
label={label}
multiline
InputLabelProps={{ shrink: true }}
InputProps={{
inputComponent: InputComponent
}}
inputProps={{ children: children }}
/>
);
};
export default OutlinedDiv;
The className passed to the inputComponent takes care of the CSS that makes this all work. You can then use this like in the following:
import React from "react";
import ReactDOM from "react-dom";
import OutlinedDiv from "./OutlinedDiv";
import Avatar from "#material-ui/core/Avatar";
import deepOrange from "#material-ui/core/colors/deepOrange";
import deepPurple from "#material-ui/core/colors/deepPurple";
import red from "#material-ui/core/colors/red";
import green from "#material-ui/core/colors/green";
import blue from "#material-ui/core/colors/blue";
import Grid from "#material-ui/core/Grid";
function App() {
return (
<div className="App">
<OutlinedDiv label="Color Picker">
<Grid container justify="center" alignItems="center">
<Avatar style={{ backgroundColor: deepOrange[500] }} />
<Avatar style={{ backgroundColor: deepPurple[500] }} />
<Avatar style={{ backgroundColor: red[500] }} />
<Avatar style={{ backgroundColor: green[500] }} />
<Avatar style={{ backgroundColor: blue[500] }} />
</Grid>
</OutlinedDiv>
<br />
<br />
<OutlinedDiv label="Custom Outlined Thing">
You can put whatever you want in here.
</OutlinedDiv>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
No need to write Outlined div component and all. As we can achieve this using FormControl, FormLabel and Formgroup.
If you follow the Outlined div logic your input fields will lose focus.
The below solution is very easy and quick you just need to wrap your code:
<FormControl component="fieldset" className="fieldset">
<FormLabel component="Legend">Title</FormLabel>
<FormGroup row>
{/*Your Input fields e.g TextField or Select e.t.c*/}
</FormGroup>
</FormControl>
Now using useStyles apply some css:
fieldset: {
width: '100%',
marginBottom: 10,
padding: 10,
border: '1px solid #ddd',
borderRadius: 5
}
The outlined textfield was really tricky to implement. When pushing that feature, we had to consider several options, each with their own drawbacks
SVG Element
Easy to build and animate, but tough to scale with the surrounding elements. If we had gone this route, we would have needed to listen for some type of resize event, which would mean either using a window resize event, which is not robust, or using a newer and less supported feature such as a ResizeObserver/MutationObserver. There are polyfills, but that would have increased the bundle size about 2K for a relatively small feature.
The SVG route is likely what will be used in the future. It is also worth noting that this is how Google's Material Components Web solves the problem.
Plain old border with a background on the label
This is by far the simplest approach, but it is also somewhat inflexible. You can see an example of this in Google's new sign-in flow. There they actually set the background color to white. This is probably a fine approach for plenty of users, but of course won't work if your background is a gradient or some similar edge case. That said, there's no need to worry about resize because it's just a border.
Fieldset and legend
This is what we ended up going with, largely because of its flexibility for end users. Fieldset and its legend component are both built-in ways of attaining pretty much this exact functionality. The big drawbacks to this are that styling across browsers is tough, and the properties we'd be animating on are not performant, such as legend width. Additionally, it's always best to use semantic HTML of course, which this is not, which means we need to use aria-hidden to instruct screen readers to ignore the element.
Depending on your goals, any one of these solutions may work best for you. Beware that getting the perfect solution that solves all of these problems may be very tricky!
Just apply the same background color on the color div as the parent's background color, you can do it by background-color: inherit like this:
<div style={inputContainerStyle}>
<div style={{
...titleStyle,
transform: 'translate(-43px, -11px) scale(0.75)',
fontSize: '17px',
color: 'rgba(0, 0, 0, 0.54)',
position: 'absolute',
background-color:'inherit' **(just add this line)**
}}
>
Color
</div>
<div
className="flex-row"
style={{
border: '1px solid rgba(0, 0, 0, 0.23)',
padding: '18.5px 14px',
borderRadius: '4px',
}}
>
{
availableColors.map(color => <div style={colorCircleStyle(color)} />)
}
</div>
</div>

How to style React Native <CheckBox> component?

Is it possible to style the React Native CheckBox component?
There is no style property listed here: https://facebook.github.io/react-native/docs/checkbox.html
I put an invalid style property on it, and the RN warning message that popped up told me all the valid CSS properties, but none of them did anything beneficial towards styling.
The component looks decent, but I want to change it from that teal color to a brand color.
Is it possible?
These properties are not working but are listed as valid style props for CheckBox:
{
height: 50, // changes the hitspace but not the checkbox itself
width: 50,
borderWidth: 1, // does nothing
backgroundColor: 'red', // makes the area around and inside the checkbox red
borderColor: 'green', // does nothing
borderStyle: 'dotted' // does nothing
}
I don't understand why it even exists if everyone just makes their own checkbox. If I did that, I wouldn't really have any use for because all it gives is
value={this.state.rememberMe}
onValueChange={() => this.toggleRememberMe()}
unless there is something magic it does under the hood. It has a decent onChange animation, but that would be deprecated instantly when I make my own and use something like <TouchableHighlight or Opacity> wrapped around an on/off image or <View>.
I can't find any info on Google except hundreds of custom checkboxes. It's actually really hard to search around them.
You can use https://github.com/react-native-community/react-native-checkbox
Android: you can use tintColors.
import CheckBox from '#react-native-community/checkbox';
.
.
.
<CheckBox
value={option.item.selected}
onValueChange={() => {}}
tintColors={{ true: '#F15927', false: 'black' }}
/>
Transform can be used to change CheckBox size.
<CheckBox
style={{ transform: [{ scaleX: 0.8 }, { scaleY: 0.8 }] }}
/>
checkbox examples
https://github.com/react-native-checkbox/react-native-checkbox
No I couldn't find a way, but wrapping it in a View was one option:
<View style={{
position: 'absolute',
right: 0,
width: 50,
height: 50,
margin: 10,
zIndex: 100,
}}>
<Checkbox
status={i === index ? 'checked' : 'unchecked'}
className=""
/>
</View>
Short answer is you simply can't. React Native uses the native Android Checkbox component, and the only customization you get to do is changing the tint colors, as seen in the react-native-checkbox community project. This prop is undocumented in the official React Native docs.
Additionally, here's the TypeScript definition for this component: AndroidCheckBoxNativeComponent.js. Notice how the only props relayed to the native component are onChange, onValueChange, testID, on, enabled and tintColors.
Yes, you can, i recommend you that use react native elements, and with this library you have 2 options, checkedColor and uncheckedColor, by default in checkedColor is green, but you can change it to what you want, for example, checkedColor={"#fff"} or checkedColor="#fff" try them, it apply for 2 options, good luck!
For IOS use onTintColor and pass the value in string onTintColor={'red'}
<CheckBox
onTintColor={Color.theme}
onCheckColor={Color.theme}
value={isSelected}
onValueChange={setSelection}
style={Style OBJECT}
/>
import CheckBox from '#react-native-community/checkbox';
const Checkbox = (props) => {
// const [isSelected, setSelection] = useState(false);
const [toggleCheckBox, setToggleCheckBox] = useState(false)
return (
<View style={[useTailwind``, styles.container]}>
<View style={styles.checkboxContainer}>
<CheckBox
disabled={false}
value={toggleCheckBox}
tintColors={{true: '#368098'}}
onCheckColor={'#6F763F'}
onValueChange={(newValue) => setToggleCheckBox(newValue)}
/>
<Text style={[useTailwind`font-normal text-base font-sans`, styles.label]}>{props.value}</Text>
</View>
{/* <Text>Is CheckBox selected: {isSelected ? "👍" : "👎"}</Text> */}
</View>
);
};
its possible now..
just simply gives tint color of the same color of background

Resources