Beginner here. As of now I can use Box like so:
<Box
p={5}
fontSize={4}
width={[ 1, 1, 1/2 ]}
color='white'
bg='magenta'>
Box
</Box>
and give it certain specified props, as it says on the site:
All margin and padding props
width: responsive width
fontSize: responsive font size
color: text color
bg: background color
flex: CSS flex shorthand property
order: CSS order property
alignSelf: CSS align-self property
Question: What if I need more props?
I know that I can extend rebass components, however, this seems to hard-code certain CSS properties into the component. E.g. If my Box is always purple I can create PurpleBox and save the color there. Or on their website there is this example:
const Container = props =>
<Box
{...props}
mx='auto'
css={{
maxWidth: '1024px'
}}
/>
Fair enough!
What what of I need to create a component, say, PositionedBox which gets an additional position prop for relative or absolute positioning?
I would like to use it like so:
<Box
p={5}
fontSize={4}
width={[ 1, 1, 1/2 ]}
color='white'
bg='magenta'
position='abs'>
Box
</Box>
Is this possible? Not sure how I could accomplish this.
You could make use of styled-components and styled-system
import styled from "styled-components";
import { position } from "styled-system";
// through interpolation
const StyledBox = styled(Box)`
// some properties
${position}
`;
// passing as a single property
const StyledBox = styled(Box)(position);
passing multiple properties
import { compose, property1, property2, ... } from "styled-system";
import StyledBox = styled(Box)(compose(property1, property2, ....));
this would extend all the position properties supported by the styled system.
list of all the out-of-the-box properties supported by styled-system here
Related
What is the best way to achieve this behavior along with React + TypeScript?
import { Button, Card } from 'src/components';
const Page = () => (
<div>
<Card mx3 p3 flex justifyContentEnd>
/* Card content */
</Card>
<Button my2 mx3>
Login
</Button>
</div>
);
For instance, mx3 will add 16px margin horizontally, my2 will add 8px margin vertically, etc., similar to how the Bootstrap framework uses classes to apply utility styles easily.
I have looked through a few component libraries with this sort of behavior in order to find a suitable solution; however, I find most do not have strong typing support. Examples are RNUILib, NativeBase, Magnus UI, etc.
You can declare your props like that:
const styles = ['mx3', 'p3', 'flex'] as const
type Styles = Record<typeof styles[number], boolean>;
Then use them like this:
type CardProps = Styles & {
other: 'props here'
}
Now, this should work:
<Card mx3 p3 flex />
You can get applied props like this:
const values = Object.entries(props).map(([key, value]) => value ? key : null).filter(Boolean)
If you see the source code of react-bootstrap, they have mapped the boolean to some CSS class using a util function of classnames package. You can do the same:
...
...
<Component
{...buttonProps}
{...props}
ref={ref}
className={classNames(
className,
prefix,
active && 'active',
variant && `${prefix}-${variant}`,
size && `${prefix}-${size}`,
props.href && props.disabled && 'disabled',
)}
/>
...
...
I am trying to add custom style on react toastify, firstly I have import these
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
than call the react toast:
const handleToast = () => {
toast("sent mail")
}
Here i adding css in toast container :
<div>
<ToastContainer toastStyle={{
marginTop: "4rem",
borderRadius: "20px",
backgroundColor: "red"
}} />
<button onClick={handleToast} className='btn btn-info'>Click here</button>
</div >
But in ToastContainer component css not working.
Thanks in advance
You can try adding the styles to a root/global CSS file.
The classNames you'd use would mainly be:
.Toastify
.Toastify__toast-container
.Toastify__progress-bar
.Toastify__toast
.Toastify__toast-body
Your problem is not clear to me.
I believe you want to style the toast itself. If so, you can easily do it by adding classes like this,
toast("Sent mail",{
className: 'black-background',
bodyClassName: "grow-font-size",
progressClassName: 'fancy-progress-bar'
});
You can add your preferred classnames on global css file, and apply your desired styles there. Here,
className: applied on the toast wrapper (this override toastClassName is set by the container )
bodyClassName: applied on the toast body (this override bodyClassName is set by the container )
progressClassName: applied on the progress bar (this override progressClassName is set by the container )
style: inline style applied to the toast
Also if you want to style the ToastContainer, you can do it the same way.
<ToastContainer toastClassName="foo" style={{ width: "2000px" }} />
toastClassName: applied on the toast wrapper
<ToastContainer className="foo" style={{ width: "2000px" }} />
To know more about how to style it in a different way, you can check out there documentation on styling from here
How to style
For some reason setting className is not styling my property:
export default class MyComponent extends Component {
render() {
return(
<div className={styles.example}>
</div>
)
}
}
const styles = StyleSheet.create({
example: {
background: 'black',
width: '100px',
height: '100px'
}
})
It just renders something like
<div class="175">
</div>
With no styling information (there is no CSS rule for the ""class"" 175)
Why is it not (as I expect) ending up with a name like styles__example___2w27N with CSS rules specified in the browser
.styles__example___2w27N {
background-color: 'black';
height: 100px;
width: 100px;
}
How do I get my CSS to be applied?
If I use style={styles.example} (instead of className) I actually get this error:
The style prop expects a mapping from style properties to values, not a string.
I would prefer to use className though because
I have specified hover and active styles, does style work with those?
I want to manually add and override some styles inline
You should be using the <View> component instead of the <div> component, as that will map the <View> component to the native view UI components for each specific platform that you're using (ie: <div> for web, android.view for android, etc.) and not the <div> element directly.
With that, the <View> element and other react-native core components are designed to work with StyleSheet. You should be applying your style to the style prop which all core components have, and not the className prop:
<View style={styles.example}>
</View>
When the above is viewed on the web, you'll see a <div> being used in the source, but on other platforms you'll see other native view UI types being used.
Stylesheet refers to React Native... are you doing react-js or react native?
Assuming you are doing react-js (because of the div), there is no such thing as stylesheet in react-js...
export default class MyComponent extends Component {
render() {
return(
<div className={styles.example}>
</div>
)
}
}
const styles = {
example: {
background: 'black',
width: '100px',
height: '100px'
}
}
I think you copied the code from a react-native document instead of the react-js...
I'm using Material-UI with my React application. I'm also using styled components and I'm viewing the app in a Chrome browser. The issue I'm having doesn't occur when using a Firefox browser.
When applying the overflow attribute in my styled component, I'm seeing this blue line towards the bottom of the modal. This only appears when I'm playing with the size of my browser window. As I gradually bring my browser window closer to normal size, the line goes away. I'm not sure why this is or what I can do to fix it.
Here is a snippet of my code:
export const ScrollableModal = styled(MUIModal)(() => ({
overflow: 'scroll',
}));
const Modal = ({ title, children, actionsLeft, actionsRight, ...rest }) => {
const wrappedTitle =
typeof title === 'string' ? <Typography>{title}</Typography> : title;
return (
<ScrollableModal {...rest}>
<Container>
I've left the rest out because it's not relevant to my question.
Here is a screenshot of what I'm describing:
I guess that's the outline property what they mentioned in the documentation for simple modal:
Notice that you can disable the outline (often blue or gold) with the outline: 0 CSS property.
First needs to be added to the current style:
const useStyles = makeStyles({
modal: {
textAlign: 'center',
width: '35vw',
backgroundColor: 'white',
opacity: 0.8,
outline: 0, // add / remove
}
});
Then it can be applied on the Container just like the following in the render:
const styles = useStyles();
return <>
<Modal open={true}>
<Container className={styles.modal}>
<p>Simple Modal</p>
</Container>
</Modal>
</>
Result by adding and removing outline property with value 0:
I guess with styled components just create a styled Container with opacity: 0 if you don't want to use makeStlyes for this purpose.
That resolved the issue for me.
I hope that helps!
I'm developing a React project using the material-ui library. I'm currently trying to add a drawer which is working fine for me. However, I'm trying to change the background color of this drawer. I've heard that the way to do this is by changing the color of the drawer's paper. I've tried adding the following tag to my CSS object:
const styles = theme => ({
background:"BLUE"
Then I reference this object in my render function using the classNames library:
render(){
const { classes } = this.props;
return(
<div className={styles.root}>
<CssBaseline />
<Drawer
variant="permanent"
className={classNames(classes.drawer, {
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})}
classes = {{
paper: classNames({
background:classes.background,
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
However, when I run this on localhost, the paper is still a plain old white. Am I missing something about the classNames library or is a special case of the paper tag? Thanks in advance and let me know if I should supply more info than this.
You have a couple issues in the code shown in your question.
For your styles, you need something more like the following:
const styles = theme => ({
drawerPaper: { background: "blue" }
});
In this case, "drawerPaper" is the key for my class name and then the object to the right contains the CSS properties for that class. When passed into withStyles, this will generate CSS like the following:
<style>
.classname-generated-for-drawerPaper-key: {
background: blue;
}
</style>
You had a class name key of "background" with the string "BLUE" as the CSS properties which will end up with CSS like the following:
<style>
.classname-generated-for-background-key: {
0: B;
1: L;
2: U;
3: E;
}
</style>
which of course is not valid CSS and will have no effect on the paper.
The second issue is in how you specify the classes:
classes = {{
paper: classNames({
background:classes.background,
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
When you pass an object to classNames, the keys of the object are the class names and the associated value controls (based on whether it is falsey or truthy) whether the class name should be included. With the syntax you used, classes.background will always be truthy which means that the class "background" (rather than the generated class name in classes.background) will be included which will have no effect since a "background" class hasn't been defined.
Instead you should have:
classes = {{
paper: classNames(classes.drawerPaper, {
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
which will unconditionally include classes.drawerPaper.
Here is a modified version of one of the Drawer demos, but with the background color of the drawer changed to blue: https://codesandbox.io/s/wqlwyk7p4l
If you're using global theme = createTheme( the color of a background paper can be set as following
const theme = createTheme({
palette: {
{
primary: colors.blue,
background: {
default: colors.grey[50],
paper: colors.common.white,
},
// ...