본문 바로가기
react

[React] node-Sass설치 & Styled-component

by 남민섭 2023. 1. 13.
728x90
반응형

node-Sass 설치

1. node버전에 맞게 설치하기 (8버젼)

npm install node-sass@8

2. node sass 제거

npm uninstall node-sass

 

실습)

ScssCompenent.scss

//변수 사용하기

$red : #fa5252;
$orange: #fd7e14;
$yellow: #fcc419;
$green: #40c057;
$blue: #339af0;
$indigo : #5c7cfa;
$violet : #7950f2;

//믹스인 만들기
@mixin square($size) {
    $calculated: 32px * $size;
    width: $calculated;
    height: $calculated;
}

.SassComponent {
    display: flex;
    .box {
        background: red;
        cursor: pointer;
        transition: 0.3s;
        &.red {
            background: $red;
            @include square(1);
        }
        &.orange {
            background: $orange;
            @include square(2);
        }
        &.yellow {
            background: $yellow;
            @include square(3);
        }
        &.green {
            background: $green;
            @include square(4);
        }
        &.blue {
            background: $blue;
            @include square(5);
        }
        &.indigo {
            background: $indigo;
            @include square(6);
        }
        &.violet {
            background: $violet;
            @include square(7);
        }
        &.hover {
            background: black;
        }
    }
}

 

SassComponent.js

import React from 'react';
import './ScssComponent.scss'

const SassComponent = () => {
    return (
        <div className='SassComponent'>
            <div className='box red'></div>
            <div className='box orange'></div>
            <div className='box yellow'></div>
            <div className='box green'></div>
            <div className='box blue'></div>
            <div className='box indigo'></div>
            <div className='box violet'></div>
        </div>
    );
};

export default SassComponent;

 

 

 


Styled-component

CSS in JavaScript 기술로 JavaScript내에서 CSS를 작성하는 라이브러리

스타일 정의를 CSS파일이 아닌 JavaScript로 작성된 컴포넌트에 바로 삽입하는 스타일 기법

클래스명을 해시값으로 자동생성, 클래스명 오염 방지

자바스크립트의 동적인 값들을 온전하게 사용가능

CSS in JS 관련 리액트 라이브러리중에서 가장 인기있는 라이브러리

 

Styled-component 참고 사이트

https://styled-components.com/docs/basics#installation

 

styled-components: Basics

Get Started with styled-components basics.

styled-components.com

 

Styled-component 라이브러리 설치

# with npm
npm install --save styled-components

위에거 에러발생시 밑에 최신버젼다운로드 입력해볼것
#최신버젼 다운로드
npm i styled-components@latest 

# with yarn
yarn add styled-components

 

설치 확인

 

 


Styled-components를 이용한 실습 1

 

 

 

App.js

import React from 'react';
import Circle from './component/Circle';


const App = () => {
    return (
        <div>
            <Circle/>
        </div>
    );
};

export default App;

 

Circle.js

import React from 'react';
import styled, {css} from 'styled-components';

const CircleDiv = styled.div`
width: 50px;
height: 50px;
background: ${props => props.color || "black"};
/* 함수에 props를 받아서 리턴해줌 컬러가 있으면 true 없으면 false
props에 color값이 있으면 color값 적용 없으면 black */

border-radius: 50%;
${props => props.big && 
css`
width: 150px;
height: 150px;
`}`;

const Circle = () => {
    return (
        <div>
            <CircleDiv color='blue'/>
            <CircleDiv color='red'/>
            <CircleDiv big/>
        </div>
    );
};

export default Circle;

 


 

Styled-components를 이용한 실습 2

 

 

App.js

import React from 'react';
import Button from './component/Button';

const App2 = () => {
    return (
        <div>
            <Button/>
        </div>
    );
};

export default App2;

 

Button.js

import React from 'react';
import styled from 'styled-components';

const Button = () => {
    const Buttoncom = styled.button`
    background: ${props => props.primary ? `palevioletred`: "white"};
    color: ${props => props.primary ? 'white': "palevioletred"};
    font-size: 1em;
    margin: 1em;
    padding: 0.25em 1em;
    border: 2px solid palevioletred;
    border-radius: 3px;
    `;
    
    const TomatoButton = styled(Buttoncom)`
    color: tomato;
    background: #fff;
    `;
    /* Buttoncom에서 기능 속성 상속받아옴 */ 
    return (
        <div>
            <Buttoncom>Normar</Buttoncom>
            <Buttoncom primary>primary</Buttoncom>
            <TomatoButton>TomatoButton</TomatoButton>
        </div>
    );
};

export default Button;

 


 

Styled-components를 이용한 실습 3

(삭제버튼 클릭시 알람띄워짐 & 알람창상태에서 취소, 삭제 클릭시 사라짐)

 

 

 

App.js

import React, { useState } from 'react';
import styled, { ThemeProvider } from 'styled-components';
import './App.css';
import ButtonTotal from './component/ButtonTotal';
import Dialog from './component/Dialog';

const AppBlock = styled.div`
width: 512px;
margin: 0 auto;
margin-top: 4em;
border: 1px solid black;
padding: 1em;
`;
function App() {
  const [dialog, setDialog] = useState(false);
  const onClick = () => {
    setDialog(true);
  };
  const onConfirm = () => {
    console.log('확인');
    setDialog(false);
  };
  const onCancel = () => {
    console.log('취소');
    setDialog(false);
  };
  return (
    <ThemeProvider theme={{
      palette:{
        blue:'#228be6',
        gray: '#495057',
        pink: '#f06595'
      }
    }}>
      <>
    <AppBlock>
      <div>
        <ButtonTotal size='large'>Button</ButtonTotal>
        <ButtonTotal>Button</ButtonTotal>
        <ButtonTotal size='small'>Button</ButtonTotal>
      </div>
      <div>
        <ButtonTotal size='large' color='pink'>Button</ButtonTotal>
        <ButtonTotal color='pink'>Button</ButtonTotal>
        <ButtonTotal size='small' color='pink'>Button</ButtonTotal>
      </div>
      <div>
        <ButtonTotal size='large' color='gray'>Button</ButtonTotal>
        <ButtonTotal color='gray'>Button</ButtonTotal>
        <ButtonTotal size='small' color='gray'>Button</ButtonTotal>
      </div>
      <div>
        <ButtonTotal size='large' color='gray' fullWidth>Button</ButtonTotal>
      </div>
      <div>
        <ButtonTotal  color='pink' fullWidth>Button</ButtonTotal>
      </div>
      <div>
        <ButtonTotal size='small' fullWidth onClick={onClick}>삭제</ButtonTotal>
      </div>
    </AppBlock>
    <Dialog title="정말로 삭제하시겠습니까?"
        confirmText="삭제"
        cancelText="취소" onConfirm={onConfirm} onCancel={onCancel} visible={dialog}> 
        데이터를 정말로 삭제하시겠습니까?
      </Dialog></>
    </ThemeProvider>
  );
}

export default App;

 

ButtonTotal.js

import React from 'react';
import styled, { css } from 'styled-components';

const ButtonTotal = ({ children,...rest}) => {
    //배경색
    const colorStyle = css`
    ${({theme,color}) => {
        const selected = theme.palette[color];
        return css`
        background: ${selected};
        `;
    }}`;
    //사이즈
    const sizes = {
        large: {
            height: '3em',
            fontSize: '1.25em',
            width: '40%'
          },
          medium: {
            height: '2.5em',
            fontSize: '1em',
            width: '25%'
          },
          small: {
            height: '1.75rem',
            fontSize: '0.875rem',
            width: '15%'
          }
    }
    const sizeStyle = css`
    ${({size})=>css`
        height:${sizes[size].height};
        font-size:${sizes[size].fontSize};
        width:${sizes[size].width};
    `}
    `;
    const fullWidthStyle = css`
        ${props=> 
        props.fullWidth && 
        css`
        width:100%;
        `
        }
    `;
    const StyledButton = styled.button`
    /*공통스타일*/
    display: inline-flex;
    outline: none;
    border: none;
    border-radius: 4px;
    color: white;
    font-weight:bold;
    cursor: pointer;
    padding: 1em;
    justify-content:center;
    /*크기*/
    font-size: 1em;
    align-items: center;
    margin: 0.5em;


    /*색상*/
    ${colorStyle}
    /*크기스타일*/
    ${sizeStyle}
    ${fullWidthStyle}
    &:hover {
        background: #1c7ed6;
    }
    &+& {
        margin-left: 1em;
    }
    `;
    return (
        <StyledButton {...rest}>{children}</StyledButton>
    );
};
ButtonTotal.defaultProps = {
    color: 'blue',
    size: 'medium'
}
export default ButtonTotal;

 

Dialog.js

import React,{useState,useEffect} from 'react';
import styled,{keyframes,css} from 'styled-components';
import ButtonTotal from './ButtonTotal';
//애니메이션
//fadeIn - keyframes만들기
const fadeIn = keyframes`
  from {
    opacity: 0
  }
  to {
    opacity: 1
  }
`;
//fadeOut - keyframes만들기
const fadeOut = keyframes`
  from {
    opacity: 1
  }
  to {
    opacity: 0
  }
`;
//slideup - keyframes만들기
const slideUp = keyframes`
  from {
    transform: translateY(200px);
  }
  to {
    transform: translateY(0px);
  }
`;
//slideDown - keyframes만들기
const slideDown = keyframes`
  from {
    transform: translateY(0px);
  }
  to {
    transform: translateY(200px);
  }
`;
//배경
//바깥 div 생성
const DarkBakcground = styled.div`
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0,0,0,0.8);
    animation-duration: 0.25s;
    animation-timing-function: ease-out;
    animation-name: ${fadeIn};
    animation-fill-mode: forwards;
    ${props =>
        props.disappear &&
        css`
          animation-name: ${fadeOut};
        `}
`;//컴펌창 블럭
//스타일이 적용된 컴퍼넌트
const DialogBlock = styled.div`
  width: 320px;
  padding: 1.5rem;
  background: white;
  border-radius: 2px;
  h3 {
    margin: 0;
    font-size: 1.5rem;
  }
  p {
    font-size: 1.125rem;
  }
  animation-duration: 0.25s;
  animation-timing-function: ease-out;
  animation-name: ${slideUp};
  animation-fill-mode: forwards;
  ${props =>
    props.disappear &&
    css`
      animation-name: ${slideDown};
    `}
`;//props가 true면 밑에 적용
const ButtonGroup = styled.div`
  margin-top: 3rem;
  display: flex;
  justify-content: flex-end;
`;

const Dialog = ({ title, children, 
confirmText, cancelText, visible,onCancel,onConfirm }) => {
     //현재 트랜지션 효과를 보여주는 중이라는 상태를 의미
    const [animate, setAnimate] = useState(false);
    
    //실제로 컴포넌트가 사라지는 시점을 지연시키기 위한 상태
    const [localVisible, setLocalVisible] = useState(visible);
    
    //useEffect 작성
    //visible 값이 true에서 false로 바뀌는 시점을 감지하여 animate값을 true로 변경
    //setTimeout함수를 사용하여 0.5초 이후에 false로 변경
    useEffect(() => {
      // visible 값이 true -> false 가 되는 것을 감지
      if (localVisible && !visible) {
        setAnimate(true);
        setTimeout(() => setAnimate(false), 250);
      }
      setLocalVisible(visible);
    }, [localVisible, visible]);
  
    if (!animate && !localVisible) return null; 
    return(
        <DarkBakcground disappear={!visible}>
           <DialogBlock disappear={!visible}>
              <h3>{title}</h3>
              <p>{children}</p>
              <ButtonGroup>
                <ButtonTotal color="gray" onClick = {onCancel}>{cancelText}</ButtonTotal>
                <ButtonTotal color="pink" onClick = {onConfirm}>{confirmText}</ButtonTotal>
              </ButtonGroup>
            </DialogBlock>
        </DarkBakcground>
    )
}
Dialog.defaultProps = {
    confirmText: '확인',
    cancelText: '취소'
  };
export default Dialog;
728x90
반응형

댓글