본문 바로가기

Front-End/React

React #12-1 (CSS - daisyUI: Button & Icon)

반응형

 

※ 사전 작업

더보기

아래 github 레포지토리로 가서 다운로드 받아서, ch03 아래의 ch03_4만 가져오기

https://github.com/yisj777s/doit-react-webapp-typescript/tree/main

 

챕터 3-5 프로젝트 폴더 생성

npx create-react-app ch03_5 --template typescript

 

패키지 설치 (버전 지정 주의)

npm i chance luxon @fontsource/material-icons
npm i -D @types/chance @types/luxon
npm i -D postcss autoprefixer tailwindcss@3.4.17 @tailwindcss/line-clamp daisyui@4.12.14

 

이전 프로젝트에서 쓰인 소스 코드들 전부 복사해온 후 page 내 파일들 삭제

cp -r ../ch03_4/src/* ./src
cp -r ../ch03_4/*.js .
rm src/pages/*

 

 

서브 디렉토리를 만들어서 실습하므로, 미리 오류가 나지 않게 처리 (상대 경로 문제)

src/copy/CopyMe.tsx

export default function CopyMe() {
  return (
    <section className="mt-4">
      <h2 className="text-5xl font-bold text-center">CopyMe</h2>
      <div className="mt-4"></div>
    </section>
  )
}

 

실습에 쓰기 위해 템플릿을 복사해오기 + 각각의 컴포넌트 디렉토리 안으로 복사 (버튼 따로, 인풋 따로)

mkdir -p src/copy/CopyMe
cd src/copy
cp CopyMe.tsx CopyMe/index.tsx
cd ../..

cd src
cp -r copy/CopyMe pages/ButtonTest
cp -r copy/CopyMe pages/InputText
cp copy/CopyMe/index.tsx pages/ModalTest.tsx
cd ..

 

App 파일에 미리 자리 깔아두기

src/App.tsx

import ButtonTest from './pages/ButtonTest'
import InputTest from './pages/InputTest'
import ModalTest from './pages/ModalTest'

export default function App() {
  return (
    <main>
      <ButtonTest />
      <InputTest />
      <ModalTest />
    </main>
  )
}

 

 

daisy CSS 컴포넌트 만들기

mkdir -p src/theme/daisyui
cd src/theme/daisyui
touch index.ts Button.tsx
cd ../../..

 

 

Button 컴포넌트 구현

src/theme/daisyui/Button.tsx

import type {FC, DetailedHTMLProps, ButtonHTMLAttributes, PropsWithChildren} from 'react'

export type ReactButtonProps = DetailedHTMLProps<
  ButtonHTMLAttributes<HTMLButtonElement>,
  HTMLButtonElement
>

export type ButtonProps = ReactButtonProps & {}

export const Button: FC<PropsWithChildren<ButtonProps>> = ({
  className: _className,
  ...buttonProps
}) => {
  const className = ['btn', _className].join(' ')
  
  return <button {...buttonProps} className={className} />
}

 

 

Button 컴포넌트 반영
src/theme/daisyui/index.ts

export * from './Button'

 

 

서브 컴포넌트 추가 생성 (기본 버튼, 버튼 사이즈 변화, 아이콘)

cd src
cp copy/CopyMe.tsx pages/ButtonTest/Basic.tsx
cp copy/CopyMe.tsx pages/ButtonTest/Size.tsx
cp copy/CopyMe.tsx pages/ButtonTest/IconTest.tsx

 


Button Test - index 구현

src/pages/ButtonTest/index.tsx

import Basic from './Basic'
import Size from './Size'
import IconTest from './IconTest'

export default function ButtonTest() {
  return (
    <section className="mt-4">
      <h2 className="text-5xl font-bold text-center">ButtonTest</h2>
      <div className="mt-4">
        <IconTest />
        <Size />
        <Basic />
      </div>
    </section>
  )
}

 

 

Button Test - 각각의 페이지 구현 (웹에 서빙)

src/pages/ButtonTest/Basic.tsx

import {Button} from '../../theme/daisyui'

export default function Basic() {
  return (
    <section className="mt-4">
      <h2 className="text-5xl font-bold text-center">Basic</h2>
      <div className="flex mt-4 justify-evenly">
        <button className="btn btn-primary">DAYSIUI BUTTON</button>
        <Button className="btn-primary">BUTTON</Button>
      </div>
    </section>
  )
}

 

 

※ 'btn' 부분 생략하기 (안해도 됨)

 

 

 

Button Test - Size

size 컴포넌트 생성

cd src/pages/ButtonTest
cp Basic.tsx Size.tsx
cd ../../..

 

src/pages/ButtonTest/Size.tsx

import {Button} from '../../theme/daisyui'

export default function Size() {
  return (
    <section className="mt-4">
      <h2 className="text-5xl font-bold text-center">Size</h2>
      <div className="flex mt-4 justify-evenly">
        <Button className="btn-lg btn-primary">BTN-LG</Button>
        <Button className="btn-md btn-primary">BTN-MD</Button>
        <Button className="btn-sm btn-primary">BTN-SM</Button>
        <Button className="btn-xs btn-primary">BTN-XS</Button>
      </div>
    </section>
  )
}

 

 

icon 컴포넌트 생성

touch src/theme/daisyui/Icon.tsx

 

icon 컴포넌트 구현

import type {FC} from 'react'
import type {ButtonProps} from './Button'
import type {IconProps as CIconProps} from '../../components'
import {Button} from './Button'
import {Icon as CIcon} from '../../components'


export type IconProps = ButtonProps &
  CIconProps & {
    iconClassName?: string
  }

export const Icon: FC<IconProps> = ({name, iconClassName, className, ...buttonProps}) => {
  
  const btnClassName = ['btn-circle', className].join(' ')
  
  return (
    <Button {...buttonProps} className={btnClassName}>
      <CIcon className={iconClassName} name={name} />
    </Button>
  )
}

 

icon 컴포넌트 반영

 

 

icon 컴포넌트 사용

import {Icon} from '../../theme/daisyui'


//prettier-ignore
export default function IconTest() {
  
  const onClick = () => alert('Icon clicked')
  
  return (
    <section className="mt-4">
      <h2 className="text-5xl font-bold text-center">IconTest</h2>

      <div className="flex items-center justify-around mt-4">
        <Icon className="btn-primary btn-lg" iconClassName="text-5xl"
              name="settings" onClick={onClick} />
        <Icon className="btn-secondary btn-md" iconClassName="text-3xl"
              name="done" onClick={onClick} />
        <Icon className="btn-accent btn-sm" iconClassName="text-xl"
              name="menu" onClick={onClick} />
        <Icon className="btn-success btn-xs" name="file_upload" onClick={onClick} />  
        
      </div>
    </section>
  )
}

 

 

 

 

 

 

반응형