Search code examples
reactjstypescriptstyled-components

How to add a background color to a styled component based on condition using react and typescript?


how can i add background color to styled component based on the condition using react and typescript?

what i am trying to do?

I have a MainComponent which renders ListContent within DragAndDropComponent.

Now when user drags a file into DragAndDrop div i want its background color change to grey.

Below is my code,

function MainComponent () {
return (
    <Wrapper>
        <SomeOtheComponent/>
        <DragAndDrop>
            <ListContent> //this is the children for the DragAndDrop component and want this to 
                //render within DragAndDrop component
                {condition_true && (
                    <FirstList/>
                )}
                {condition_true && (
                    <SecondList/>
                )}
            </ListContent>
        </Wrapper>
    );
}


const DragAndDrop: React.FC = ({ children }) => { //here i am passing children
    const [dragging, setDragging] = useState(false);
    const [dragCounter, setDragCounter] = useState(0);

    React.useEffect(() => {
        // componentDidMount()
        setDragCounter(0);
    }, []);

    const handleDrag = (e: any) => {
        e.preventDefault();
        e.stopPropagation();
    };

    const handleDragIn = (e: any) => {
        e.preventDefault();
        e.stopPropagation();
        setDragCounter((prev: number) => prev + 1);
        if (e.dataTransfer.files) {
            setDragging(true);
        }
    };

    const handleDragOut = (e: any) => {
        e.preventDefault();
        e.stopPropagation();
        setDragCounter((prev: number) => prev - 1);
        if (dragCounter === 0) {
            setDragging(false);
        }
    }; 

    const handleDrop = (e: any) => {
        e.preventDefault();
        e.stopPropagation();
        setDragging(false);
        if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
            e.dataTransfer.clearData();
            setDragCounter(0);
        }
    };

    return (
        <DropZone //i want to change background color to this div if dragging true.
            ref={dropRef}
            onDragEnter={handleDragIn}
            onDragLeave={handleDragOut}
            onDragOver={handleDrag}
            onDrop={handleDrop}
        >  
            {children}
        </DropZone>
    );
};


const DropZone = styled.div`
    height: 100%;
    //backgroun-color: how to change background color to grey if dragging state true.
`;

Could someone help me with this. thanks.


Solution

  • Use a function that is passed the props object. Here I've destructured dragging and if truthy return the background: grey rule, otherwise it returns no rule.

    passed props

    const DropZone = styled.div`
      height: 100%;
      ${({ dragging }) => dragging && 'background-color:  grey;'}
    `;
    

    EDIT: Add dragging prop type (<{ dragging?: boolean }>) for typescript

    const DropZone = styled.div<{ dragging?: boolean }>`
      height: 100%;
      ${({ dragging }) => dragging && 'background-color:  grey;'}
    `;
    

    Usage

    <DropZone
      ref={dropRef}
      dragging={dragging} // <-- pass dragging as prop here
      onDragEnter={handleDragIn}
      onDragLeave={handleDragOut}
      onDragOver={handleDrag}
      onDrop={handleDrop}
    >  
      {children}
    </DropZone>