Search code examples
cssreactjsanimationcarouselreact-functional-component

Create Reactjs Component like Carousel using css


I'm working on react functional component that initially contains 1 cards like the following:

Initial State

When i fill the fields and hit enter, i want to animate this to left and make it smaller and create another one like the picture:

When first cards inserted

And finally, when i have one box in left side and another in center and again i fill data and hit enter, i want to hide the small box in left with animation and animate filled box to left with resize and add new item from right side with animations that starts with 0px width and height goes larger while moving to center like following: What i want

Always i see the box for new in center and if i have registered any record, i have one previous box with smaller size. And the animation is important

All that i want is somthing like Carousel. I spent a lot of time but did not get results.

I need the css hero helps to get me out of hole.

Thanks to All


Solution

  • After 4 days of hard work, finally i got it. I answerd my question for those with same requirement.

    import { Typography, TextField, Box } from "@mui/material"
    import { useEffect, useRef, useState } from 'react';
    import Layout from '../layout'
    import styles from './serial.module.css';
    
    const Serial = () => {
        const [state, setState] = useState({
            items: [
                {
                    serial: '',
                    activity: ''
                },
            ],
            newItem: {
                serialRegistered: false,
                serial: '',
                activity: ''
            }
        })
    
        const serialInputRef = useRef();
        const activityInputRef = useRef();
    
        useEffect(() => {
            if (serialInputRef.current, activityInputRef.current) {
                if (state.newItem.serialRegistered === false) {
                    serialInputRef.current.focus();
                }
                else {
    
                    activityInputRef.current.focus();
                }
            }
    
        }, [state])
    
        return (
            <Layout>
                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', flexDirection: 'row', direction: 'ltr' }}>
                    {
    
    
                        state.items.map((item, index) => {
                            console.log(state.items);
                            if (index === state.items.length - 1 && state.items.length > 1) { // new
    
                                return (
                                    <div className={styles.i1}>
                                        <Typography>
                                            {item.serial}
                                        </Typography>
                                        <br />
                                        <Typography>
                                            {item.activity}
                                        </Typography>
                                    </div>
                                )
                            }
                            else if (index === state.items.length - 2 || state.items.length === 1) { // current
                                return (
                                    <div className={styles.i2}>
                                        <Box style={{ width: '100%', margin: 'auto' }} component="form" noValidate onSubmit={e => { e.preventDefault(); }}>
                                            <TextField
                                                inputRef={serialInputRef}
                                                label="سریال"
                                                placeholder='سریال'
                                                value={state.newItem.serial}
                                                margin="normal"
                                                disabled={state.newItem.serialRegistered}
                                                required fullWidth focused autoFocus
                                                autoComplete=""
    
                                                onKeyPress={(e) => {
                                                    if (e.code === 'Enter') {
                                                        setState(prev => {
                                                            return {
                                                                ...prev,
                                                                newItem: {
                                                                    ...prev.newItem,
                                                                    serialRegistered: true,
                                                                }
                                                            }
                                                        })
                                                    } else {
                                                        setState(prev => {
                                                            return {
                                                                ...prev,
                                                                newItem: {
                                                                    ...prev.newItem,
                                                                    serial: prev.newItem.serial + e.key,
                                                                }
                                                            }
                                                        })
                                                    }
                                                }}
                                                onBlur={(e) => {
                                                    if (state.newItem.serialRegistered === false) {
                                                        e.target.focus()
                                                    }
                                                }} />
                                        </Box>
    
                                        <Box style={{ width: '100%', margin: 'auto' }} component="form" noValidate onSubmit={e => { e.preventDefault(); }}>
                                            <TextField
                                                inputRef={activityInputRef}
                                                label="فعالیت"
                                                placeholder='فعالیت'
                                                margin="normal"
                                                value={state.newItem.activity}
                                                required fullWidth focused autoFocus
                                                autoComplete={false}
                                                onKeyPress={(e) => {
                                                    if (e.code === 'Enter') {
                                                        setState(prev => {
                                                            console.log("prev", prev)
                                                            console.log("prev 1", prev.items.slice(0, prev.items.length - 1));
                                                            console.log("prev 1", prev.items.slice(0, prev.items.length - 2));
    
                                                            return {
                                                                ...prev,
                                                                items: [...prev.items.slice(0, prev.items.length - 1), prev.newItem, {
                                                                    serial: '',
                                                                    activity: ''
                                                                }],
                                                                newItem: {
                                                                    serialRegistered: false,
                                                                    serial: '',
                                                                    activity: ''
                                                                },
                                                            }
                                                        })
                                                    } else {
                                                        setState(prev => {
                                                            return {
                                                                ...prev,
                                                                newItem: {
                                                                    ...prev.newItem,
                                                                    activity: prev.newItem.activity + e.key,
                                                                }
                                                            }
                                                        })
                                                    }
                                                }}
                                                onBlur={(e) => {
                                                    if (state.newItem.serialRegistered === true) {
                                                        e.target.focus()
                                                    }
                                                }} />
                                        </Box>
                                    </div>
                                )
                            }
                            else if (index === state.items.length - 3) { // previous
                                return (
                                    <div className={styles.i3}>
                                        <Box style={{ width: '100%', margin: 'auto' }} component="form" noValidate onSubmit={e => { e.preventDefault(); }}>
                                            <TextField
                                                size="small"
                                                label="سریال"
                                                placeholder='سریال'
                                                value={item.serial}
                                                margin="normal"
                                                disabled
                                                fullWidth focused autoFocus
                                                autoComplete="" />
                                        </Box>
    
                                        <Box style={{ width: '100%', margin: 'auto' }} component="form" noValidate onSubmit={e => { e.preventDefault(); }}>
                                            <TextField
                                                size="small"
                                                label="فعالیت"
                                                placeholder='فعالیت'
                                                margin="normal"
                                                value={item.activity}
                                                disabled
                                                fullWidth focused autoFocus
                                                autoComplete={false} />
                                        </Box>
                                    </div>
                                )
                            }
                            else if (index === state.items.length - 4) { // 2 previous
                                return (
                                    <div className={styles.i4}>
                                        <Box style={{ width: '100%', margin: 'auto' }} component="form" noValidate onSubmit={e => { e.preventDefault(); }}>
                                            <TextField
                                                className={styles.i4Content}
                                                size="small"
                                                label="سریال"
                                                placeholder='سریال'
                                                value={item.serial}
                                                margin="normal"
                                                disabled
                                                required fullWidth focused autoFocus
                                                autoComplete="" />
                                        </Box>
    
                                        <Box style={{ width: '100%', margin: 'auto' }} component="form" noValidate onSubmit={e => { e.preventDefault(); }}>
                                            <TextField
                                                className={styles.i4Content}
                                                size="small"
                                                label="فعالیت"
                                                placeholder='فعالیت'
                                                margin="normal"
                                                value={item.activity}
                                                required fullWidth focused autoFocus
                                                autoComplete={false} />
                                        </Box>
                                    </div>
                                )
                            }
                            else {
                                return (<></>)
                            }
                        })
                    }
                </div>
            </Layout>
        )
    }
    
    export default Serial
    .i1 {
      /* new */
      display: none;
    }
    
    .i2 {
      /* current */
      position: relative;
      padding: 20px;
      width: 350px;
      height: 210px;
      background-color: white;
      border: 1px solid #bdb6b6;
      border-radius: 10px;
      margin: 30px;
      display: grid;
      grid-template-rows: 1fr 1fr;
      justify-items: center;
      animation-name: i2kf;
      -webkit-animation-name: i2kf;
      animation-duration: 2s;
      -webkit-animation-duration: 2s;
    }
    
    @keyframes i2kf {
      from {
        opacity: .6;
        transform: scale(.1);
        right: -350px;
        width: 350px;
        height: 210px;
      }
      to {
        opacity: 1;
        transform: scale(1);
        right: 0px;
        width: 350px;
        height: 210px;
      }
    }
    
    .i3 {
      /* prev */
      position: relative;
      padding: 20px;
      width: 230px;
      height: 130px;
      /* transform: scale(.5); */
      background-color: white;
      border: 1px solid #bdb6b6;
      border-radius: 10px;
      margin: 30px;
      display: grid;
      grid-template-rows: 1fr 1fr;
      justify-items: center;
      animation-name: i3kf;
      -webkit-animation-name: i3kf;
      animation-duration: 2s;
      -webkit-animation-duration: 2s;
      /* animation-delay: .2ms;
        -webkit-animation-delay: .2s; */
    }
    
    @keyframes i3kf {
      from {
        right: -400px;
        width: 350px;
        height: 210px;
        /* transform: scale(.1); */
      }
      to {
        right: 0px;
        width: 230px;
        height: 130px;
      }
    }
    
    .i4 {
      /* prev */
      position: relative;
      padding: 20px;
      background-color: white;
      border: 1px solid #bdb6b6;
      border-radius: 10px;
      margin: 30px;
      width: 0px;
      height: 0px;
      /* display: none; */
      opacity: 0;
      animation-name: i4kf;
      -webkit-animation-name: i4kf;
      animation-duration: 3s;
      -webkit-animation-duration: 3s;
      /* animation-delay: .1ms;
        -webkit-animation-delay: .1s; */
    }
    
    @keyframes i4kf {
      from {
        transform: scale(.9);
        right: -260px;
        width: 240px;
        height: 150px;
        opacity: 1;
      }
      to {
        /* transform: scale(0); */
        right: 0px;
        width: 0px;
        height: 0px;
        opacity: 0;
      }
    }
    
    .i4Content {
      opacity: 0;
      animation-name: i4kfContent;
      -webkit-animation-name: i4kfContent;
      animation-duration: 1s;
      -webkit-animation-duration: 1s;
    }
    
    @keyframes i4kfContent {
      from {
        opacity: .5;
      }
      to {
        opacity: 0;
      }
    }

    It's my first code snippet and i could not resolve error. I have some dependancy like material-ui and some other Component.

    If you remove Layout and add dependancy, it works fine.