How to create a login screen with changing background images? - reactjs

I have a login page. As per the wireframes, there are images in the background and they change in every few seconds.
Consider it like a splash screen with a login form. I have developed the login form. But the splash screen is the issue.
How do I achieve this with react.js?
Any leads would be helpful.

The gist is to setup a background image container (likely taking 100% of the view height and width) with the following CSS:
// keep image from scrolling when content is scrollable
background-attachment: fixed;
// center the image within the container
background-position: center;
// scale the image to cover the container the smaller quantity of width or height
background-size: cover;
width: 100vw;
height: 100vh;
Then in code choose your flavor of CSS-in-JS. I like styled-components, but for brevity I'll use an in-line style attribute:
style={{ backgroundImage: `url(${/* pass reference to image */})` }}
Sample Component:
import bgImgArray from './assets/img';
function App() {
const [index, setIndex] = useState(0);
useEffect(() => {
const timer = setInterval(() => setIndex(i => i + 1), 5000);
return () => clearInterval(timer);
}, []);
const bgImg = bgImgArray[index % bgImgArray.length];
return (
<div
className="App backgroundContainer"
style={{
backgroundImage: `url(${bgImg})`
}}
>
/* container content, children, etc.. */
</div>
);
}

Related

How can I implement css hover effect in react inline-styling?

I am trying to implement a hover effect in the react component using react inline-styling.
const InfoWindow: React.FC<IInfoWindowProps> = ({ room }) => {
const info_window_image = {
width: "100%",
height: "168px",
background: `url(${room.pictures[0].image.large}) no-repeat`,
backgroundSize: "contain",
cursor: 'pointer'
};
return (
<div className="info_window_container">
<div style={info_window_image} />
</div>
)
};
div tag under info_window_container gets style object info_window_image .
I can successfully receive an image from API but I want to give zoom-in animation when the user hovers the image in the component.
I gave className to the div and styled in CSS file however it does not work. Styles I declared in CSS file do not render.
How can I make hover or focus effect in react-inline-styling?

Recreate Ant Design Pro like Sider/Drawer in Antd React App

I'm trying to configure the style/css of my Antd React app to be mobile ready.
My main menu uses the Reactive Sider Menu seen here.
My issue is when I'm viewing with a mobile viewport it's kinda ugly and it squashes everything outside of the menu. And the little tab to expand/condense the menu covers some of my other components.
I'd much prefer the design that they have in the Ant Design Pro demo.
But I'm not sure how to create this exactly. Has anyone attempted it before? It seems to use a Drawer when it's in a mobile viewport as opposed to using the Sider in the Layout API.
Figured this out.
Essentially my solution (not sure if this is what they actually did in Ant Design Pro) is to use the Reactive Sider Menu example for the desktop and use a Drawer for mobile.
The same Toggle button in the Reactive Sider Menu example can hide/close the Sider (in Desktop) and Drawer (in mobile).
The trick was using CSS Media Queries to hide the Drawer in Desktop and hide the Sider in mobile so each could do their thing.
CSS
.hideOnMobile {
display: none;
}
#media only screen and (min-width: 768px) {
.hideOnMobile {
display: block;
}
}
.hideOnDesktop {
display: block;
}
#media only screen and (min-width: 768px) {
.hideOnDesktop {
display: none;
}
}
App.js
const App = () => {
// sider and drawer toggle
const [isToggled, setToggled] = useState(false);
const toggleTrueFalse = () => setToggled(!isToggled);
const onClose = () => {
setToggled(false);
};
return (
<Layout style={{ minHeight: "100vh" }}>
<Drawer
placement="left"
onClose={onClose}
closable={false}
visible={isToggled}
className="hideOnDesktop"
bodyStyle={{ backgroundColor: "#001529", padding: "0" }}
>
<Navbar />
</Drawer>
<Sider
breakpoint="lg"
collapsedWidth="0"
collapsed={isToggled}
onBreakpoint={(broken) => {
setToggled(broken);
}}
className="hideOnMobile"
>
<Navbar />
</Sider>
<Layout className="site-layout">
<Header
className="site-layout-background"
style={{ padding: 0 }}
>
<Row>
{React.createElement(
isToggled ? MenuUnfoldOutlined : MenuFoldOutlined,
{
className: "trigger",
onClick: toggleTrueFalse,
}
)}
<TopNavbar />
</Row>
</Header>
...
Also per the Antd docs for the Drawer component you can use the bodyStyle prop to set the background color and remove the padding so the menu sits flush to the sides of the Drawer.

Styled Components Props React js

I pass a property to my styled component. Basically I pass his height that starts with 400px.
And when I click a button it will go to 30px, but the way I did my div starts with 400px and when I click the button it goes to 30px and then doesn't expand the height size anymore:
export default function Menu() {
const [open, setOpen] = useState(true); // declare new state variable "open" with setter
const handleClick = e => {
e.preventDefault();
setOpen(false);
};
return (
<DivMenuButton height={open ? '400px' : '30px'}>
<button
style={{ margin:0, padding: 0, height: "30px", width: "100%", borderRadius:'0px' }}
onClick={handleClick}
>
Button
</button>
</DivMenuButton>
);
}
My styled component:
import React from 'react';
import styled from 'styled-components';
export const DivMenuButton = styled.div`
border: 0px;
background-color: #000; // was wrong syntax
width: 200px;
height: ${props => props.height}
`;
code:
https://codesandbox.io/s/beautiful-nightingale-fsm58
Your code is actually correct (almost).
The props and styled components parts are correct.
The thing you did wrong is that you always set open to false when clicking the button, instead of setting it to the opposite of what it was before.
So, instead of doing this:
const handleClick = e => {
e.preventDefault();
setOpen(false);
};
you should do this:
const handleClick = e => {
e.preventDefault();
setOpen(!open);
};

Material UI responsive based on element size

I'm using React and MaterialUI to build a system that will display widgets inside another (not React-based) web site. I'd like to make the widgets responsive, but they need to respond to their own container width rather than the window width, as I won't know how much of the page the widget will take up.
Options I've considered:
Polling the container size on an interval basis
Polling the container size on window resize events
Setting up the theme breakpoints based on the container and window sizes at startup
These all seem rather ugly solutions to me. Is there an elegant way to do what I want?
Instead of breakpoints you can listen to changes to the component size. You can use react-use hook useMeasure to achieve that (it relies on ResizeObserver, which is supported by all major browsers), like in the following example:
/** #jsx jsx */
import { css, jsx } from '#emotion/core';
import { faAddressBook, faCoffee } from '#fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { useMeasure } from 'react-use';
const useMyComponentStyle = (params) => {
const { color } = params;
const [ref, { width }] = useMeasure();
const borderColor = width < 150 ? 'red' : width < 400 ? 'yellow' : 'green';
const icon = width < 250 ? faCoffee : faAddressBook;
const style = css`
color: ${color};
padding: 10px;
border: 1px solid ${borderColor};
`;
return {
ref,
style,
icon,
width,
};
};
export const MyComponent = (props) => {
const { ref, style, icon, width } = useMyComponentStyle(props);
return (
<div ref={ref} css={style}>
<FontAwesomeIcon icon={icon} />
{props.children} [[{parseInt('' + width)}px]]
</div>
);
};
const containerStyle = css`
padding: 100px 200px;
border: 1px solid blue;
`;
export const MyContainer = () => (
<div css={containerStyle}>
<MyComponent color='blue'></MyComponent>
</div>
);
ReactDOM.render(<MyContainer />, document.getElementById('root'));
The example above uses emotion for the css styles, but the style could be defined using another library, like jss or styled components, or even plain react inline style.
The component MyComponent is included inside the container component MyContainer that has left and right padding with value 200px, and you can see as you resize your browser view that the border color of MyComponent is based on the size of the component itself (red if the width of the component is less than 150px, yellow if it's less than 400px, otherwise it's green), not based on the size of the window.
To make various #material-ui/core elements take up only as much space as the container you place them in, I'd use the Grid component.
I've used the following:
<Grid container spacing={24}>
<Grid item>
Your content here
</Grid>
</Grid>
If you further want your grid item to be responsive to things like screen size, you may do:
const grid = {
xs: 24,
sm: 24,
md: 24,
lg: 12,
xl: 12,
};
and
<Grid item {...grid}>
Documentation: https://material-ui.com/layout/grid/

How to disable click events for props.children in React?

How can any click events be disabled for props.children?
const Example = props => (
<div>
<div>This can be clicked</div>
{props.children} /* These can't be clicked */
</div>
)
I am rendering a PDF page using react-pdf and want the user to be able to drag a custom selection marquee (like in Photoshop...). As it is, the PDF page under or inside the marquee element still registers mouse events upon dragging, like text selection.
There is an easy, but not robust way to do this:
const Example = props => (
<div style={{pointerEvents:'none'}}>
<div style={{pointerEvents:'auto'}}>This can be clicked</div>
{props.children}
</div>
)
It is not robust, because if any of the children have pointer-events set to auto, they will be clickable too. See if it fits your needs. Also, it will kill hover and other mouse events.
Use CSS Grid to put a div on top!
A transparent div rendered on top of another div will intercept click events.
CSS Grid can be used (abused?) to make a single grid area (using grid-template-areas) and assign multiple elements to it (using grid-area).
JSX
const ClickGuard = ({allow, block}) => (
<div className='click-guard-area'>
<div className='click-guard-allowed'>{props.allow}</div>
<div className='click-guard-block' />
<div className='click-guard-blocked'>{props.block}</div>
</div>
)
CSS
.click-guard-area {
display: grid;
grid-template-areas: 'click-guard';
height: 100%;
width: 100%;
}
.click-guard-allowed {
grid-area: click-guard;
height: 100%;
width: 100%;
z-index: 2;
}
.click-guard-block {
grid-area: click-guard;
height: 100%;
width: 100%;
z-index: 1;
}
.click-guard-blocked {
grid-area: click-guard;
height: 100%;
width: 100%;
}
Note that ClickGuard expects two props: allow and block. These should be JSX. The React docs explain passing React elements here.
<ClickGuard
allow={<div>I can be clicked!</div>}
block={<div>No clicks for me. 😞</div>}
/>
You cannot change the props within an element thus its children props.
An alternative solution may be possible with React.cloneElement,
Here is a simple peace of code for you:
const Example = props => (
<div>
<div>This can be clicked</div>
{props.children.map((child)=>
React.cloneElement(child, {
disabled: true
})
)}
</div>
)

Resources