i'm currently i'm working in a project that is required to have a "Inset Fab" button between containers. I saw in the Material Design documentation that the name of the component is called "Inset FAB", i'd got some tutorials on google (but didn't find many) on how to implement, but normally they are "workaround" (setting a background border with radius behind the button). I'm still puzzled in how to do it.
Currently i'm using the MUI/Material UI 5.
Example of inset Fab
from what I understand inset is done through box shadows.
specifically
boxShadow: "0px 0px 0px 5px white inset"
here is a code sandbox I threw together
import React from "react";
import ReactDOM from "react-dom";
import { Box, Fab } from "#material-ui/core";
const appBarStyle = {
height: "100px",
backgroundColor: "blue",
position: "relative"
};
const fabWithInset = {
position: "absolute",
backgroundColor: "red",
boxShadow: "0px 0px 0px 0px white inset",
left: "50%",
bottom: "0px",
transform: "translate(0%,50%)",
"&:onclick": {
boxShadow: "0px 0px 0px 5px white inset"
}
};
function App() {
return (
<Box style={appBarStyle}>
<Fab style={fabWithInset} />
</Box>
);
}
ReactDOM.render(<App />, document.querySelector("#app"));
Related
A component has been created that I can not edit:
import * as React from 'react'
import styled from '#emotion/styled'
import FlexRow from '../../layouts/FlexRow'
const RowContainer = styled('div')<TableRowProps>(
({theme, padding, active, hoverActive=true}): any => ({
position: 'relative',
borderBottom: `1px solid ${theme.concrete}`,
borderLeft: active ? `4px solid ${theme.primaryDark}` : 'none',
boxShadow: active ? `inset 16px 0px 0px 0px ${theme.alabaster}, inset 0px 2px 4px -2px rgba(44, 51, 55, 0.16)` : 'none',
backgroundColor: active ? `${theme.alabaster}` : 'none',
padding: padding ?? `20px 16px 20px ${active ? '12px' : '16px'}`,
'&:hover': hoverActive ? {
borderLeft: `4px solid ${theme.schist}`,
paddingLeft: '12px',
backgroundColor: `${theme.alabaster}`,
boxShadow: `inset 16px 0px 0px 0px ${theme.alabaster}, inset 0px 2px 4px -2px rgba(44, 51, 55, 0.16)`
} : {}
})
)
type TableRowProps = {
theme?: any
padding?: string
active?: boolean,
hoverActive?: boolean
}
export const Row = (props) => <RowContainer padding={props.padding} active={props.active} hoverActive={props.hoverActive} ><FlexRow {...props} /></RowContainer>
I'm using this component with a custom Table component like this:
<Table.Row {...flexProps} className="TableRow">
I'm wanting to remove the padding from Row and have tried:
<Table.Row style={{ padding: 0 }}>...</Table.Row>
How can I access it's props and make changes to the component?
Given that the Row component forwards any padding prop to the RowContainer where it uses it for the padding style (falling back to 20px 16px 20px ${active ? '12px' : '16px'}), you can simply set padding="0" when you use it
<Table.Row padding="0">...</Table.Row>
I am trying to design a simple report with the format as shown in the following Figma file using React and Material UI. However, I am encountering a challenge when designing the slanting edges of the divs as shown on the report. Plus the purple border. This is what I have done so far, but it is far from being perfect:
const leftDiv = {
content: "",
position: "absolute",
top: "50%",
right: 0,
width: "100%",
height: "50%",
backgroundColor: 'rgb(255, 255, 255)',
clipPath: "polygon(0 0, 0% 0%, 100% 100%, 0% 100%)"
}
const rightDiv = {
position: "absolute",
bottom: 0,
right: 0,
display: 'inline-block',
width: 0,
height: 0,
borderStyle: 'solid',
borderWidth: '0 0 500px 100vw',
borderColor: 'transparent transparent #FFFFFF transparent',
}
const contentDiv = {
backgroundColor: 'rgb(255, 255, 255)',
width: "100%",
height: "100%",
clipPath: "polygon(100% 0, 100% 0%, 100% 100%, 0% 100%)"
}
const Coverpage = () => {
return (
<Container>
<Grid>
<Paper>
<Box sx={{ position: 'relative', width: '100%' }}>
<CardMedia
component='img'
alt="cover page image"
image='https://unsplash.com/photos/vbxyFxlgpjM'
/>
<Box style={leftDiv}></Box>
<Box style={rightDiv}>
<Box style={contentDiv}>
<Box sx={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', alignItems: 'flex-end', textAlign: 'right', pr: 8 }}>
<Typography sx={{ fontSize: '24px', mb: 2 }}>Lorem ipsum</Typography>
<Typography sx={{ fontSize: '48px', fontWeight: 'bold', textTransform: 'uppercase', color: '#000133' }}>Lorem ipsum</Typography>
<Typography sx={{ fontSize: '64px', fontWeight: 'bold', textTransform: 'uppercase', color: 'blue' }}>Lorem ipsum</Typography>
</Box>
</Box>
</Box>
</Box>
</Paper>
</Grid>
</Container>
);
}
export default Coverpage;
I found using clipPath as the easiest, even though I would prefer using triangles to design the slanting edges since later, I am planning to use react-pdf-renderer which I am not sure if it supports clipPath in its CSS styling.
I will appreciate a pointer to the right direction.
Dan touched on the purple border. About the slanted div you can use this trick:
.slanted{
height: 0;
width: 0;
border-top: solid 100px transparent;
border-right: solid 50vw blue;
border-left: solid 50vw blue;
border-bottom: solid 100px blue;
}
You're making a div with no height or width. The borders meet along a diagonal line and so you can have a triangle effect.
You can use an additional div for the text
Edit: making the borders responsive
To make the border trick dynamic you can use some JS:
function App() {
const footerRef = React.useRef()
useEffect(() => {
window.addEventListener('resize', setBorders)
return () => {
window.removeEventListener('resize', setBorders)
}
}, [])
useEffect(() => {
if (!footerRef.current) return
setBorders()
}, [footerRef])
const setBorders = () => {
let containerWidth = document.querySelector('.container').clientWidth
let footerStyle = footerRef.current.style
footerStyle.borderRightWidth = containerWidth/2+'px'
footerStyle.borderLeftWidth = containerWidth/2+'px'
}
return (
<div className='App'>
<div className='container'>
<div className='footer' ref={footerRef}>
</div>
</div>
</div>
);
}
export default App
We are adding a 'resize' eventListener to the window that will trigger the setBorders() function. In this function we select the container element and set the width of the footer borders to be half of it.
To make sure the function also fires on initial load I added a useEffect which will fire when the footer is created and its Ref is set. You can also use a callback ref instead.
The css, I assumed the footer will be static height:
.container{
height: 200px;
width: 100%;
background: red;
}
.footer{
position: relative;
height: 0;
width: 0;
top: calc(100% - 100px);
/*border-top width + border-bottom width = 100px*/
border-top: 50px solid transparent;
border-bottom: 50px solid green;
border-right: solid blue;
border-left: solid blue;
}
If you don't mind making the container position: relative; you can then just do:
.footer{
position: absolute;
bottom: 0;
}
You just need to use a simple CSS transform on the element.
transform: skew(-15deg, -15deg);
this is a react app. my css class is not changing even though the state assign to track the boolean value is changing. I've passed my states accordingly for this still not working. here is the github url
my app.js file -
import React, { useState } from "react";
// Import Styles
import "./styles/App.css";
// Import Components
import Hello from "./components/Hello";
import Rectangle from "./components/Rectangle";
import Button from "./components/Button";
function App() {
const [colorStatus, setColorStatus] = useState(false);
return (
<div className="App">
<Hello />
<Rectangle colorStatus={colorStatus} />
<Button colorStatus={colorStatus} setColorStatus={setColorStatus} />
</div>
);
}
export default App;
button.js -\
import React from "react";
const Button = ({ colorStatus, setColorStatus }) => {
return (
<div className="button">
<button className="btn-1" onClick={() => setColorStatus(!colorStatus)}>
Press
</button>
</div>
);
};
export default Button;
rectangle.js -
import React from "react";
const Rectangle = ({colorStatus}) => {
return <div className={`rectangle ${colorStatus ? 'active-rectangle' : '' }`}></div>;
};
export default Rectangle;
necessary css -
.rectangle {
width: 50vw;
height: 50vh;
background: rgba(255, 0, 0, 0.4);
position: fixed;
top: 30%;
left: 35%;
}
.active-rectangle {
width: 50vw;
height: 50vh;
background: rgba(0, green, 0, 0.4);
position: fixed;
top: 30%;
left: 35%;
}
Your .active-rectangle css-rule needs correction like so :-
.active-rectangle {
width: 50vw;
height: 50vh;
background: rgba(0, 255, 0, 0.4);
position: fixed;
top: 30%;
left: 35%;
}
So your state should be getting updated and the active-rectangle class is getting applied. Just the background property isn't getting applied properly. Rest must still be getting applied.
background isn't getting applied properly because you cannot use green when a decimal value is expected inside rgba(...).
Actually your css class is getting changed (according to the url you provided).
Problem seems to be with the usage of background: rgba(0, green, 0, 0.4). Specifically in rgba(0, green, 0, 0.4).
Instead of green, it should have been a number from 0 to 255 to denote the green part of the colour.
G of R-G-B-A from rgba function you are using
checkout https://cssreference.io/property/background-color/
The problem, as said here before is the background property
Lets refactor the code a bit while we are in it.
.rectangle {
width: 50vw;
height: 50vh;
background: rgba(255, 0, 0, 0.4);
position: fixed;
top: 30%;
left: 35%;
}
.rectangle.active {
background: rgba(0, 255, 0, 0.4);
}
import React from "react";
const Rectangle = ({colorStatus}) => {
return <div className={`rectangle ${colorStatus ? 'active' : '' }`}></div>;
};
export default Rectangle;
Sandbox: https://codesandbox.io/s/friendly-galileo-gwzbh?file=/src/components/Rectangle.js
EDIT: after further testing it seems that each time the component is re-rendered material-ui's makeStyles is executed again, while JSS's createUseStyles is NOT!
I have a component that has to dynamically change the styling based on the state. When I use makeStyles provided with material-ui the code works perfectly:
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
position: "relative",
borderRadius: filteredItems.length > 0 ? "4px 4px 0 0" : "4px 4px 4px 4px", // this is the relevant line
backgroundColor: "white",
color: "black",
},
}));
But I don't want to use material-ui, I just want to use JSS. Unfortunately it doesn't work. It looks like filteredItems.length > 0 always returns false, so I guess that createUseStyles for some reason is executed differently than makeStyles:
import { createUseStyles } from "react-jss";
const useStyles = createUseStyles(theme => ({
root: {
position: "relative",
borderRadius: filteredItems.length > 0 ? "4px 4px 0 0" : "4px 4px 4px 4px", // this is the relevant line
backgroundColor: "white",
color: "black",
},
}));
I know that material-ui runs under the hood JSS so I'm puzzled by this behaviour. I thought about adding two CSS classes and toggle them within my JSX, but I think sorting out the issue in the styling is the cleanest solution here. Anyone knows why this is happening or how to fix the issue?
EDIT2: To fix the issue I simply created two classes and toggled them within JSX:
const useStyles = createUseStyles(() => {
return ({
root: {
position: "relative",
borderRadius: "4px 4px 4px 4px",
backgroundColor: "white",
color: "black",
},
withItems: {
borderRadius: "4px 4px 0 0",
},
})
});
And then:
<div className={filteredItems.length > 0 ? `${classes.root} ${classes.withItems}` : classes.root}>
Have you tried this approach?
const useStyles = makeStyles({
root: {
position: "relative",
backgroundColor: "white",
color: "black",
borderRadius: props.withItems ? "4px 4px 0 0" : "4px 4px 4px 4px",
// or
// borderRadius: "4px 4px 4px 4px",
// borderRadius: props.withItems && "4px 4px 0 0",
color: props => props.color,
},
});
render() {
const classes = useStyles({ withItems: filteredItems.length > 0 });
return <div className={classes.root} />;
}
I have this code in the app index.js file.
As you can see its got some styles and also a button component.
Here is the full code:
import React from 'react';
import ReactDOM from 'react-dom';
//Styles Here
var buttonStyle1 = {
margin: '10px 10px 10px 0',
padding: '4px 20px',
border: '1px solid grey'
};
var buttonStyle2 = {
margin: '10px 10px 10px 0',
padding: '4px 10px',
border: '1px solid blue',
borderRadius: 0
};
//Component Here
var Button = React.createClass({
render: function () {
return (
<button
name={this.props.name}
className={this.props.className}
style={buttonStyle1}
onClick={this.handleClick}>{this.props.label}
</button>
);
},
handleClick: function() {
alert('Button pressed name is: '+ this.props.name);
}
});
module.exports = Button;
ReactDOM.render(
<div>
<Button name="button1" label="Button" className="btn btn-success" />
<Button name="button200" label="Label Here" className="btn btn-default" />
<Button name="button20" label="Label again" className="btn btn-default" />
</div>,
document.getElementById('root')
);
What I nee to do is to add the part where it says //Styles Here into an external js file and the same to the part where it says //Component Here so they are both on external files.
How can I do this?
**//Update:**
Here's the current code all now in the same level as index.js
//index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import Button from './Buttons';
ReactDOM.render(
<Button style={{fontSize: '14px'}} name='Hi' label='button'/>,
document.getElementById('root')
);
//ButtonStyles.js
module.exports = {
buttonStyle1 : {
margin: '10px 10px 10px 0',
padding: '4px 20px',
border: '1px solid grey'
};
buttonStyle2 : {
margin: '10px 10px 10px 0',
padding: '4px 10px',
border: '1px solid blue',
borderRadius: 0
};
}
//Buttons.js
import React from 'react';
import ReactDOM from 'react-dom';
var Button = React.createClass({
render: function () {
return (
<button
name={this.props.name}
className={this.props.className}
style={this.props.style}
onClick={this.handleClick}>{this.props.label}
</button>
);
},
handleClick: function() {
alert('Button pressed name is: '+ this.props.name);
}
});
No button is showing
Create the separate file for Button component, button.js like this:
import React from 'react';
import ReactDOM from 'react-dom';
var Button = React.createClass({
render: function () {
return (
<button
name={this.props.name}
className={this.props.className}
style={this.props.style}
onClick={this.handleClick}>{this.props.label}
</button>
);
},
handleClick: function() {
alert('Button pressed name is: '+ this.props.name);
}
});
export default Button;
And import this file wherever you want like this:
import Button from './button' //path to file
Use it like this:
<Button />
For styling, create a file style.js, like this:
module.exports = {
buttonStyle1 : {
margin: '10px 10px 10px 0',
padding: '4px 20px',
border: '1px solid grey'
},
buttonStyle2 : {
margin: '10px 10px 10px 0',
padding: '4px 10px',
border: '1px solid blue',
borderRadius: 0
}
}
import this file like this:
import Style from './style' // path
And use it like this: <p style={Style.buttonStyle2}></p>
Let me know if you need any help in this.
check the jsfiddle: https://jsfiddle.net/jty8rggk/
Create a file called ButtonStyles.js:
//ButtonStyles.js
export default {
buttonStyle1: {
margin: '10px 10px 10px 0',
padding: '4px 20px',
border: '1px solid grey'
},
buttonStyle2: {
margin: '10px 10px 10px 0',
padding: '4px 10px',
border: '1px solid blue',
borderRadius: 0
}
}
After that you can create a file for your component called Button.js and then import and use the styles in your component like below.
import React from 'react';
import styles from './ButtonStyles'
//Component Here
var Button = React.createClass({
render: function () {
return (
<button
name={this.props.name}
className={this.props.className}
style={styles.buttonStyle1}
onClick={this.handleClick}>{this.props.label}
</button>
);
},
handleClick: function() {
alert('Button pressed name is: '+ this.props.name);
}
});
module.exports = Button;