-
Notifications
You must be signed in to change notification settings - Fork 5
MOAMOA FE Design System
๋ชจ์๋ชจ์์ ๋์์ธ ์์คํ ์ ์ ๋ฆฝํฉ๋๋ค.
flex์ ๊ด๋ จ๋ props๋ฅผ ๋ฐ์ต๋๋ค.
ex) alignItems, justifyContens ๋ฑ
grid์ ๊ด๋ จ๋ props๋ฅผ ๋ฐ์ต๋๋ค.
ex) columns, columnGap, rows, rowGap ๋ฑ
Flex์ Grid๋ mediaQuery์์ฑ์ ๊ฐ์ฒด๋ก ๋ฐ์ต๋๋ค.
const Wrapper = (children, width, height, padding, margin, border ... ๋ฑ์ ๋ค์ํ props) => <div>{children}</div>
;
๊ณตํต ์ปดํฌ๋ํธ๋ ์์ฃผ ์ฌ์ฉ๋ ๊ฒ๋ค๋ก ์ง์ ํฉ๋๋ค.
์ปดํฌ๋ํธ ๊ฐ๋ฐ์ props๋ง ์ ์ฃผ๋ฉด ๋ค๋ฅธ๊ณณ์์๋ ์ธ ์ ์์๊ฒ ๊ฐ์๋ ๊ณตํต ์ปดํฌ๋ํธ๋ก ์น๊ฒฉ์ํต๋๋ค.
์๋ฅผ๋ค์ด ์ปดํฌ๋ํธ๋ ์๋์ ๊ฐ์ด ์์ฑํฉ๋๋ค.
import Button from '@components/button';
import UnorderedList from '@components/unorderd-list';
// Props๋ฅผ ๋งจ ์์ ๋ก๋๋ค
export type StudyListProps = {
children?: React.ReactNode;
variant?: 'primary' | 'secondary';
onAddButtonClick: React.MouseEventHandler<HTMLButtonElement>;
onRemoveButtonClick: React.MouseEventHandler<HTMLButtonElement>;
};
// Component๋ ํ์ดํ ํจ์๋ก ํํํ๊ณ , React.FC<Props>๋ก ํ์
์ ๋ช
์ํฉ๋๋ค
// - return type์ ๋ ์ฝ๊ฒ ๊ฐ์ ํ ์ ์์ต๋๋ค
const StudyList: React.FC<StudyListProps> = ({
children,
variant,
onAddButtonClick: handleAddButtonClick,
onRemoveButtonClick: handleRemoveButtonClick,
}) => {
return (
<Self>
<List>
<Item>๋ฆฌํฉํ ๋ง ์คํฐ๋</Item>
<Item>ํ๋ก ํธ ์คํฐ๋</Item>
<Item>์๋ฐ ์คํฐ๋</Item>
</List>
<AddButton onClick={handleAddButtonClick}>์ถ๊ฐํ๊ธฐ</AddButton>
<RemoveButton onClick={handleRemoveButtonClick}>์ญ์ ํ๊ธฐ</RemoveButton>
</Self>
);
};
export default StudyList;
// styled component๋ component์ ๊ฐ์ด ๋ก๋๋ค. ์๋ํ๋ฉด
// 1. ์์ง์ฑ -> ์์์ ๋ฐ๋ก ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ค์ ๋ฐ๋ก ์๋์ชฝ์ ๋ ์ผ๋ก์จ ์์ฃผ ์ฝ๊ฐ์ด์ง๋ง ์์ง์ฑ์ ๋์
๋๋ค.
// 2. ์บก์ํ -> ์ด ์ปดํฌ๋ํธ์์๋ง ์ฌ์ฉํ๋ ํ์์ปดํฌ๋ํธ(Self, StudyList, AddStudyButton ..)๋ค์ ์ธ๋ถ์ ๋
ธ์ถํ์ง ์์ต๋๋ค.
// 3. styled ํ์ผ์ ๋ฐ๋ก ๋ง๋ค๋ฉด, VSC์์ ๊ฒ์ํ ๋ ์กฐ๊ธ ๋ถํธํฉ๋๋ค.
// Self๋ฅผ ๋ค๋ฅธ ์ปดํฌ๋ํธ์์ ์์๋ฐ์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด, (์ฌ์ฉํ๋์ชฝ์์ ์ด๊ณณ์) Component๋ฅผ importํด์ ์์ ๋ฐ์ผ๋ฉด ๋ฉ๋๋ค.
// ๊ฐ์ฅ ๋ฐ๊นฅ ์ปดํฌ๋ํธ๋ Self๋ก ๋ช
๋ช
ํฉ๋๋ค.
// ์๋๋ผ๋ฉด S.StudyList๋ผ๊ณ ํ๋๋ฐ S๋ฅผ ๋นผ๊ณ ์ถ์๋ฐ ๋นผ๋ฉด ์ปดํฌ๋ํธ์ ์ด๋ฆ์ด ๊ฐ์์ง๊ธฐ ๋๋ฌธ์ Self๋ก ๋ช
๋ช
ํ์ต๋๋ค.
const Self = styled.div`
${({ theme }) => css`
padding: 10px;
max-width: 500px;
border: 2px solid ${theme.color.black}; // color๋ theme์ ์ ์ํ color๋ฅผ ์ฌ์ฉํฉ๋๋ค
`}
`;
type ListProps = {
theme: Theme;
children: React.ReactNode;
};
const List: React.FC<ListProps> = ({ theme, children }) => (
// custom props๋ ํ์ฉ๋ css property๋ง ๋ฃ์ ์ ์์ต๋๋ค.
// css props๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์๋ฌด๊ฑฐ๋ ๋ฃ์ ์ ์๊ธฐ ๋๋ฌธ์ ๋์์ธ์ ๊ฐ์ ํ ์ ์๊ฒ๋ฉ๋๋ค.
<UnorderedList custom={{ marginBottom: '20px', backgroundColor: theme.colors.green }}>{children}</UnorderedList>
);
type ItemProps = {
theme: Theme;
children: React.ReactNode;
};
const Item: React.FC<ItemProps> = ({ theme, children }) => (
<UnorderedList.Item custom={{ padding: '4px' }}>{children}</UnorderedList.Item>
);
type AddButtonProps = {
children: React.ReactNode;
onClick: React.MouseEventHandler<HTMLButtonElement>;
};
// ๊ณตํต ์ปดํฌ๋ํธ๋ ์ด๋ ๊ฒ ๋๋ฉ์ธ์ ๋ํ ์ ๋ณด๋ฅผ ์
ํ์ ํ์ฉํฉ๋๋ค.
const AddButton = ({ children, onClick: handleClick }: AddButtonProps) => (
<Button custom={{ marginBottom: '20px' }} variant="primary" onClick={handleClick}>
{children}
</Button>
);
type RemoveButtonProps = AddButtonProps;
const RemoveButton = ({ children, onClick: handleClick }: RemoveButtonProps) => (
<Button custom={{ marginBottom: '30px' }} variant="danger" onClick={handleClick}>
{children}
</Button>
);
custom prop์ ํด๋น ์ปดํฌ๋ํธ์ ํต์ฌ์ด ์๋ ์คํ์ผ์ ๋ฃ์๋ ์ฌ์ฉํฉ๋๋ค.
๋จ!! ์๋ฌด ์คํ์ผ์ด๋ ๋ฃ๋๊ฒ์ด ์๋๋ผ, ์ปดํฌ๋ํธ๊ฐ ํ์ฉํ ์คํ์ผ๋ง ๋ฃ์ ์ ์๋๋ก ์ค์ ํ ์ ์์ต๋๋ค.
import { css } from '@emotion/react';
import { type CSSProperties as OriginalCSSProperties } from '@emotion/serialize';
import { BreakPoint, BreakpointsFor, mqDown } from '@styles/responsive';
type KeyOfOriginalCSSProperties = keyof OriginalCSSProperties;
export type PickAllowedCSSProperties<CSSProperties extends KeyOfOriginalCSSProperties> = Pick<
OriginalCSSProperties,
CSSProperties
>;
export type CSSPropertyWithValue<AllowedCSSProperties extends KeyOfOriginalCSSProperties> = {
[K in keyof PickAllowedCSSProperties<AllowedCSSProperties>]: OriginalCSSProperties[K];
};
export type ResponsiveCSSPropertyWithValue<AllowedCSSProperties extends KeyOfOriginalCSSProperties> = BreakpointsFor<
CSSPropertyWithValue<AllowedCSSProperties>
>;
export type CustomCSS<AllowedCSSProperties extends KeyOfOriginalCSSProperties> =
CSSPropertyWithValue<AllowedCSSProperties> & { responsive?: ResponsiveCSSPropertyWithValue<AllowedCSSProperties> };
export const getResponsiveStyle = <AllowedCSSProperties extends KeyOfOriginalCSSProperties>(
breakPoint: BreakPoint,
styleObject: CSSPropertyWithValue<AllowedCSSProperties>,
) => {
return css`
${mqDown(breakPoint)} {
${styleObject}
}
`;
};
export const resolveCustomCSS = <AllowedCSSProperties extends KeyOfOriginalCSSProperties>(
custom?: CustomCSS<AllowedCSSProperties>,
) => {
if (!custom) return css``;
const { responsive, ...defaultStyle } = custom;
if (responsive) {
const { xs, sm, md, lg, xl, xxl, xxxl } = responsive;
const xsStyle = xs && getResponsiveStyle<AllowedCSSProperties>('xs', xs);
const smStyle = sm && getResponsiveStyle<AllowedCSSProperties>('sm', sm);
const mdStyle = md && getResponsiveStyle<AllowedCSSProperties>('md', md);
const lgStyle = lg && getResponsiveStyle<AllowedCSSProperties>('lg', lg);
const xlStyle = xl && getResponsiveStyle<AllowedCSSProperties>('xl', xl);
const xxlStyle = xxl && getResponsiveStyle<AllowedCSSProperties>('xxl', xxl);
const xxxlStyle = xxxl && getResponsiveStyle<AllowedCSSProperties>('xxxl', xxxl);
return css`
${defaultStyle}
// ์ฐ์ ์์๊ฐ ์ค์ํฉ๋๋ค!! xxxl -> xs ์์ผ๋ก ๋์์ผ ํฉ๋๋ค
${xxxlStyle}
${xxlStyle}
${xlStyle}
${lgStyle}
${mdStyle}
${smStyle}
${xsStyle}
`;
}
return css`
${defaultStyle}
`;
};
type ButtonProps = {
children: React.ReactNode;
type: 'submit' | 'button';
fluid?: boolean;
disabled?: boolean;
onClick?: React.MouseEventHandler<HTMLButtonElement>;
custom?: CustomCSS<'marginBottom'>;
};
const Button: React.FC<ButtonProps> = ({ children, type = 'button', disabled, onClick, custom }) => {
<button css={resolveCustomCSS(custom)} disabled={disabled} type={type} onClick={onClick}>
{children}
</button>;
};
2px ๋จ์๋ก ์์ฑํฉ๋๋ค.