Develop/React & React Native

[React / RN] Styled Component 💅🏻

안다희 2020. 2. 16. 03:10
728x90

https://academy.nomadcoders.co/courses/styled-components-like-a-boss/lectures/4713642

 

#1 Setup and a trip to the past

Make CSS great again.

academy.nomadcoders.co

https://github.com/daheeahn/awesomeness-styled-components

 

daheeahn/awesomeness-styled-components

Learn About Styled Component. Contribute to daheeahn/awesomeness-styled-components development by creating an account on GitHub.

github.com

 

<강의가 필요한 이유>

 

SASS, webpack 작업 오래 걸림

css 파일 새로 만들고 클래스명 만들고 오락가락

SASS, variable, mixin 좋아하는가?

 

RN, React Web css코드 공유하고 싶을 때

 

SASS 코드를 SASS 코드 없이 짜고,

css 파일 없이 css 코드를 짜고

클래스명 없이 css를 작업하고

이걸 RN으로 공유 가능!!

 

미디어 쿼리는 RN에서 할 수 있음

 

 

1. Setup and a trip to the past

- github repo

- cra (create-react-app)

- 필요없는 파일 삭제

 

버튼을 바꾸는데 hover active state 배경색을 바꾸고

 

src/App.css

 

rgb color!!!!!!!

 

https://flatuicolors.com/

 

Flat UI Colors 2 - 14 Color Palettes, 280 colors 🎨

280 handpicked colors ready for COPY & PASTE

flatuicolors.com

 

src/App.js

import "./App.css";

import React from "react";

function App() {
  return (
    <>
      <button className="button button--success">Hello</button>
      <button className="button button--danger">Hello</button>
    </>
  );
}

export default App;

 

src/App.css

.button {
  border-radius: 50px;
  padding: 5px;
  min-width: 120px;
  color: white;
  font-weight: 600;
  -webkit-appearance: none;
  cursor: pointer;
}

.button:active,
.button:focus {
  outline: none;
}

.button--success {
  background-color: #2980b9;
}

.button--danger {
  background-color: #e67e22;
}
 
이렇게 하면 좀 불편... 이제 styled component 해보자!
 
 
2. Hello World with Styled Components
yarn add styled-components

 

src/App.js

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

function App() {
  return (
    <Container>
      <Button>Hi</Button>
      <Button danger>Hi 2</Button>
    </Container>
  );
}

const Container = styled.div`
  height: 100vh;
  width: 100%;
  background-color: #bdc3c7;
`;

// 스타일링 하려는 html 요소임
const Button = styled.button`
  border-radius: 50px;
  padding: 5px;
  min-width: 120px;
  color: white;
  font-weight: 600;
  -webkit-appearance: none;
  cursor: pointer;
  &:active,
  &:focus {
    outline: none;
  }
  background-color: ${props => (props.danger ? "#e74c3c" : "#2ecc71")};
`;

export default App;

styled.div

styled.button

. 뒤에 오는건 무조건 html 태그여야 함!

 

 

src/App.css 삭제!

 

 

3. injectGlobal and Extend

https://www.styled-components.com/docs/api#createglobalstyle

import styled, { createGlobalStyle } from "styled-components";

const GlobalStyle = createGlobalStyle` // add this code
  body {
    padding: 0;
    margin: 0;
  }
`;

function App() {
  return (
    <Container>
      <GlobalStyle /> // add this code
      <Button>Hi</Button>
      <Button danger>Hi 2</Button>
    </Container>
  );
}

 

버튼을 앵커, 링크로 사용하고 싶으면? 나의 컴포넌트를 재활용하고 싶다.

extensions

import styled from "styled-components";

function App() {
  return (
    <Container>
      <Button>Hi</Button>
      <Button danger>Hi 2</Button>
      <Anchor href="https://naver.com">Go to Goggle</Anchor>
    </Container>
  );
}

const Container = styled.div`
  height: 100vh;
  width: 100%;
  background-color: #bdc3c7;
`;

// 스타일링 하려는 html 요소임
const Button = styled.button`
  border-radius: 50px;
  padding: 5px;
  min-width: 120px;
  color: white;
  font-weight: 600;
  -webkit-appearance: none;
  cursor: pointer;
  &:active,
  &:focus {
    outline: none;
  }
  background-color: ${props => (props.danger ? "#e74c3c" : "#2ecc71")};
`;

// styled components는 똑똑해서 Anchor가 h 레퍼런스가 있는걸 알아
// extend하려면 styled()임. a 대신 h1으로 할 수도 있겠지. 클래스명 없음! 어썸!
const Anchor = styled(Button.withComponent("a"))`
  text-decoration: none;
`; // const Anchor = Button.withComponent("a")

export default App;

styled()

a 태그로 바꿨음!

그리고 text-decoration으로 a태그에 붙는 밑줄을 none으로 없앴지. 익스텐션임! 그걸 styled()로 구현한거임.

 

4. Animations

danger이면 그 버튼 계속 돌게 만들거야

import styled, { createGlobalStyle, css, keyframes } from "styled-components";

function App() {
  return (
    <Container>
      <Button>Hi</Button>
      <Button danger rotationTime={5}>Hi 2</Button>
      <Anchor href="https://naver.com">Go to Goggle</Anchor>
    </Container>
  );
}

// 스타일링 하려는 html 요소임
const Button = styled.button`
  border-radius: 50px;
  padding: 5px;
  min-width: 120px;
  color: white;
  font-weight: 600;
  -webkit-appearance: none;
  cursor: pointer;
  &:active,
  &:focus {
    outline: none;
  }
  background-color: ${props => (props.danger ? "#e74c3c" : "#2ecc71")};
  ${props => { // add this!!!!
    if (props.danger) {
      return css`
        // animation: ${rotation} 2s linear infinite;
        animation: ${rotation} ${props.rotationTime}s linear infinite; // props로 받을 수도 있지!
      `;
    }
  }}
`;

// add this!!!!!
const rotation = keyframes`
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
`;

export default App;

 

컴포넌트에서 애니메이션 스피드를 바꿀 수 없어. state를 사용해야 될걸?

Awesome!

 

5. Extra Attributes and Mixins

- attrs

src/App.js

attributes를 보여줄거야. 가끔 set an attribute할 때가 있거든

import styled from "styled-components";

const Input = styled.input.attrs({ // attrs 주목!
  required: true // 무슨 뜻?
})`
  border-radius: 5px;
`;

function App() {
  return (
    <Container>
      <Input placeholder={"input..."} />
    </Container>
  );
}

const Container = styled.div`
  height: 100vh;
  width: 100%;
  background-color: #bdc3c7;
`;

export default App;

required보이지?

근데 이게 무슨 뜻이지?

 

 

- mixins

css 그룹이야. 내가 그룹화하고 싶은. 여러 장소에서 쓰고 싶으니까!

2가지 방법이 있어. 다른 컴포넌트 쓰고 확장하거나, 믹신을 쓰는 방법!

 

import { css } ! css 규칙을 그룹화하게 도와줘.

 

헤더, 푸터, 콤비네이션 만들 때 유용할거야.

shared file에 넣으면 다른 사람도 쓸 수 있음.

 

import styled, { css } from "styled-components";

// just css block. 사용하고 싶을 때마다 쓰고싶은 스타일.
// add this!!!
const awesomeCard = css`
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  background-color: white;
  border-radius: 10px;
  padding: 20px;
`;

const Input = styled.input.attrs({
  required: true
})`
  border: none;
  ${awesomeCard} // add this!!!
`;

function App() {
  return (
    <Container>
      <GlobalStyle />
      <Input placeholder={"input..."} />
    </Container>
  );
}

const Container = styled.div`
  height: 100vh;
  width: 100%;
  ${awesomeCard} // add this!!!
  background-color: #bdc3c7;
`;

export default App;

 

이렇게 활용 가능

 

6. Theming

디자이너랑 작업하면 색상 꽤 중요하다,

모든 border는 blue여야 한다. 근데 갑자기 red로 바꿔달라 하면?

그래서 theme를 만들거야

 

src/App.js

import styled, { ThemeProvider, createGlobalStyle } from "styled-components"; // add ThemeProvider

import React from "react";
import theme from "./theme";

const GlobalStyle = createGlobalStyle`
  body {
    padding: 0;
    margin: 0;
  }
`;

const Container = styled.div`
  height: 100vh;
  width: 100%;
  background-color: pink;
`;

const Card = styled.div`
  background-color: red;
`;

// themeProvider로 감싸줘서 가능! darkmode or 색맹.. 등등 테마를 로딩할 수 있어. depth가 themeProvider로부터 좀 있는데도 불구하고!
const Button = styled.button`
  border-radius: 30px;
  padding: 25px 15px;
  background-color: ${props => props.theme.successColor}; // add this code!!!
`;

function App() {
  return (
    <ThemeProvider theme={theme}> // add!!!!!
      <Container>
        <GlobalStyle />
        <Form />
      </Container>
    </ThemeProvider>
  );
}

// theme이 어디에나 존재하는거야. 리덕스처럼
const Form = () => (
  <Card>
    <Button>Hello~~~~</Button>
  </Card>
);

export default App;

 

src/theme.js 생성

const theme = {
  mainColor: "#3498db",
  dangerColor: "#e74c3c",
  successColor: "#2ecc71"
};

export default theme;

 

 

7. nesting

SAS에서 볼 수 있음. styled components에서도 사용가능.

 

컨테이너 안의 모든 카드 선택하고 싶으면, 해당 엘리먼트를 레퍼런스하고

const Card = styled.div`
  background-color: red;
`;

// first-child last-child note? noth? 등등 last-child만 블루가 된다...
const Container = styled.div`
  height: 100vh;
  width: 100%;
  background-color: pink;
  ${Card}:last-child {
    background-color: blue;
  }
`;

<Container>안에 <Card>가 있으면 적용된다!!!!! last-child면

<Container>

  <Card> // red

  <Card> // red

  <Card> <--- 얘만 백그라운드 컬러 blue

</Container>

 

8. expo app

/styled-awesomeness에서

// expo init
// 나는 RN 깔아야지
react-native init styled_native

강의에선 exp init인데 나는 expo가 먹힘 뭔가 설치가 다른게 필요한가봐

 

yarn global upgrade expo
// 업그레이드 필요 시

 

/styled-awesomeness/style_native

yarn add styled-components

 

styled_native/App.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import {SafeAreaView, StatusBar, Text, View} from 'react-native'; // 이거 없어도 됨!!!!!

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

// paddingBottom 이런거 안해도 되지.
const Container = styled.View`
  flex: 1;
  justify-content: center;
  align-items: center;
  padding: 10px 20px;
`;

const Title = styled.Text`
  font-size: 40px;
  font-weight: 600;
`;

const App = () => {
  return (
    <Container>
      <Title>hi</Title>
    </Container>
  );
};

export default App;

RN에서도 스타일 컴포넌트 사용 가능하다~

 

https://github.com/necolas/react-native-web

 

necolas/react-native-web

React Native for Web. Contribute to necolas/react-native-web development by creating an account on GitHub.

github.com

RN에서 쓴 styled components를 웹으로 바꿈.

View -> div

Text -> p 같은걸로

 

행복도 상승 스피드 상승

 

 

9. 예시

https://github.com/nomadcoders/styled-awesomeness/blob/fdb5d0d7ca29ab83dc4519c03ed76ab37a9d5c34/extras.md

 

nomadcoders/styled-awesomeness

Learning Styled Components by example. Contribute to nomadcoders/styled-awesomeness development by creating an account on GitHub.

github.com

 

https://github.com/serranoarevalo/styled-awesomeness/blob/master/07-extras/extras.md

 

serranoarevalo/styled-awesomeness

Learning Styled Components by example. Contribute to serranoarevalo/styled-awesomeness development by creating an account on GitHub.

github.com

import breakpoint from 'styled-components-breakpoint'
import Flex, { FlexItem } from 'styled-flex-component';

써봐~ 위 링크에 예시 있음

breakpoint - responsive design에 좋음

flex

 

 

styled-flex-component

flex center full