새로운 프로젝트의 시작으로 Next.js
를 이용한 웹 앱을 만들기로 했다. css의 경우 팀원들과 상의를 해서 Tailwindcss
를 사용하기로 했다. 우선 디자인을 마무리하고 나온 대표 색상들을 추가 해줬다.
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--textRed: #ff5a5a;
--primaryRed: #ff8585;
--validRed: #db6666;
--orange: #ffaa85;
--primaryBlue: #8eb9ff;
--secondaryBlue: #85b6ff;
--navBlue: #76aaff;
--lightBlue: #85daff;
--textGrey: #545f71;
--borderGrey: #dadada;
--cancelGrey: #b4b4b4;
--tagRed: #ffbfbf;
--tagGreen: #ace1ae;
--tagPurple: #c8bfff;
--mint: #74ffe6;
}
import type { Config } from 'tailwindcss';
const config: Config = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
},
colors: {
red: {
text: 'var(--textRed)',
primary: 'var(--primaryRed)',
valid: 'var(--validRed)',
},
orange: 'var(--orange)',
blue: {
primary: 'var(--primaryBlue)',
secondary: 'var(--secondaryBlue)',
nav: 'var(--navBlue)',
light: 'var(--lightBlue)',
},
grey: {
text: 'var(--textGrey)',
border: 'var(--borderGrey)',
cancel: 'var(--cancelGrey)',
},
tag: {
red: 'var(--tagRed)',
green: 'var(--tagGreen)',
purple: 'var(--tagPurple)',
},
mint: 'var(--mint)',
},
},
},
plugins: [],
};
export default config;
스타일에 관한 내용은 globals.css에서 전체적으로 관리하기 위해 :root
를 이용해 색상을 지정 해준 뒤 태일윈드에서 사용해주기 위해 tailwind.config.ts
에 분류 해 넣어 줬다.
최초에는 props문법과 템플릿리터럴 문법을 사용해 css에 직접 수정하려고 했다.
<div className={`flex justify-center items-center w-${props.width} h-${props.height} bg-${props.bgColor} text-xl text-white rounded-xl`}>
{props.title}
</div>
만들고 난 뒤 테스트를 하는중 props를 잘 못받아오는 경우가 있었다. 이에 공식문서를 찾아본 결과 css를 동적으로 사용면 안된다는 결과를 얻었다.
동적 클래스 이름
Tailwind가 클래스 이름을 추출하는 방법의 가장 중요한 의미는 소스 파일에서 끊어지지 않은 완전한 문자열로 존재하는 클래스만 찾아낸다는 것입니다.
문자열 보간을 사용하거나 부분적인 클래스 이름을 함께 연결하면 Tailwind는 해당 클래스 이름을 찾지 못하므로 해당 CSS를 생성하지 않습니다.
https://tailwindcss.com/docs/content-configuration#dynamic-class-names
tailwinds에서는 이러한 경우 어떤식으로 만들어야하는지 예시를 들어줬다.
function Button({ color, children }) {
const colorVariants = {
blue: 'bg-blue-600 hover:bg-blue-500 text-white',
red: 'bg-red-500 hover:bg-red-400 text-white',
yellow: 'bg-yellow-300 hover:bg-yellow-400 text-black',
}
return (
<button className={`${colorVariants[color]} ...`}>
{children}
</button>
)
}
위와 같이 css가 끊지기 않게 작성을 해줘야한다.
import Image from 'next/image';
import Delete from '../../public/delete.svg';
import Plus from '../../public/plus.svg';
interface ButtonProps {
title: string;
icon?: 'delete' | 'plus';
items: keyof typeof itemVariants;
}
const ICONS = {
delete: Delete,
plus: Plus,
};
const itemVariants = {
redSmall:
'flex justify-center items-center w-32 h-9 bg-red-primary text-xs text-white rounded-xl',
redMedium:
'flex justify-center items-center w-36 h-11 bg-red-primary text-xl text-white rounded-xl',
redLarge:
'flex justify-center items-center w-80 h-14 bg-red-primary text-xl text-white rounded-xl',
blueSmall:
'flex justify-center items-center w-32 h-9 bg-blue-primary text-xs text-white rounded-xl',
blueMedium:
'flex justify-center items-center w-36 h-11 bg-blue-primary text-xl text-white rounded-xl',
blueLarge:
'flex justify-center items-center w-80 h-14 bg-blue-primary text-xl text-white rounded-xl',
};
export default function Button(props: ButtonProps) {
const IconImage = props.icon ? ICONS[props.icon] : null;
return (
<div className={`${itemVariants[props.items]}`}>
{IconImage && <Image src={IconImage} alt={props.icon || ''} className='mr-2' />}
{props.title}
{/* 버튼 이름 */}
</div>
);
}
위의 예시와 같이 원하는 스타일을 미리 입력을하고 props.items
에 원하는 스타일을 입력하면 그에 맞는 버튼 컴포넌트가 보일 것이다.
공용컴포넌트를 만드는것은 전에 사용했던 styled-component에 비해 번거로운 편인것 같다. 하지만 Tailwind CSS
는 Next.js 공식문서에서 Next.js와 매우 잘 작동하는 유틸리티 우선 CSS 프레임워크
라고 하니 적응이 필요할듯 하다.