Skip to content

Latest commit

ย 

History

History
342 lines (267 loc) ยท 9.11 KB

README.md

File metadata and controls

342 lines (267 loc) ยท 9.11 KB

๐Ÿ“ฆ๐ŸŽจ cocorig-ui

๐Ÿ““ ๊ธฐ๋ก

์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๊ณผ์ •์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

1 ์ผ์ฐจ

setting , npm ๋ฐฐํฌ ํ…Œ์ŠคํŠธ

2 ์ผ์ฐจ

์—ญํ• ์— ๋งž๋Š” color ์ƒ‰์ƒ ์ง€์ •

  • const ๋‹จ์–ธ์œผ๋กœ ์ƒ์ˆ˜ ๊ด€๋ฆฌ

    Color๊ฐ์ฒด๋ฅผ ์ •์˜ํ•  ๋•Œ TypeScript์˜ as const๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•˜๋ฉด, ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ํƒ€์ž…์ด ์ถ”๋ก ๋˜์–ด ์ง€์ •๋œ ๊ฐ’ ์™ธ์˜ ๊ฐ’์„ ํ• ๋‹นํ•  ์ˆ˜ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์˜๋„ํ•˜์ง€ ์•Š์€ ๊ฐ’ ๋ณ€๊ฒฝ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

3 ์ผ์ฐจ

spacing ์Šคํƒ€์ผ


spacing์€ @emotion์˜ SerializedStyles๋ฅผ return ํ•˜๋Š” ํ•จ์ˆ˜๋กœ ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ Emotion css props ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ์ด ์—๋Ÿฌ๋Š” Emotion์˜ css ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋œ ์Šคํƒ€์ผ ๊ฐ์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ ํ˜„์ƒ์ด๋‹ค.
<button css={[spacing.mx(3), spacing.my(4)]}>๋ฒ„ํŠผ</button>
  • ์—๋Ÿฌ ๋ฉ”์„ธ์ง€

You have tried to stringify object returned from css function. It isn't supposed to be used directly (e.g. as value of the className prop), but rather handed to emotion so it can handle it (e.g. as value of css prop).,You have tried to stringify object returned from css function. It isn't supposed to be used directly (e.g. as value of the className prop), but rather handed to emotion so it can handle it (e.g. as value of css prop).

<button css={spacing.my(4)}>๋ฒ„ํŠผ</button>
  • ์—๋Ÿฌ ๋ฉ”์„ธ์ง€

css="You have tried to stringify object returned from css function. It isn't supposed to be used directly (e.g. as value of the className prop), but rather handed to emotion so it can handle it (e.g. as value of css prop)."

๋”ฐ๋ผ์„œ ๊ฐ ํŽ˜์ด์ง€๋งˆ๋‹ค /** @jsxImportSource @emotion/react */ ์ฃผ์„์„ ๋‹ฌ์•„์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๊ณ , craco ์„ค์น˜ ๋ฐ ์„ค์ •ํ•ด ์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”๋ฐ ์•„๋ž˜์™€ ๊ฐ™์ด styled ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ด์„œ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.

import { spacing } from "./spacing";
import styled from "@emotion/styled";

const Button = styled.button`
  ${[spacing.mx(2), spacing.my(6)]}
`;
const Box = styled.div`
  ${spacing.m(2)}
`;
export const Test = () => {
  return (
    <>
      <Button>button</Button>
      <Box>box</Box>
    </>
  );
4 ์ผ์ฐจ

typography ์ปดํฌ๋„ŒํŠธ

5 ์ผ์ฐจ

spacing ์Šคํƒ€์ผ

6 ์ผ์ฐจ

button ์ปดํฌ๋„ŒํŠธ

7 ์ผ์ฐจ

input ์ปดํฌ๋„ŒํŠธ

input ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋˜ ์ค‘ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ์ฒ˜๋Ÿผ ์‚ฌ์ด์ฆˆ๋ฅผ prop์œผ๋กœ ๋ฐ›์•„์™€์„œ ์Šคํƒ€์ผ์„ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒŒ ์ข‹์„ ๊ฑฐ ๊ฐ™๋‹ค ์ƒ๊ฐํ•ด์„œ width: 100%, height: auto๋กœ ํ•˜๊ณ  padding ๊ฐ’์œผ๋กœ๋งŒ ์‚ฌ์ด์ฆˆ๋ฅผ ์กฐ์ ˆํ•˜๊ฒŒ ๋” ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

์ฒ˜์Œ์—” ์•„๋ž˜์™€ ๊ฐ™์ด icon์ด ์žˆ๋Š” input๊ณผ ์—†๋Š” Input์˜ padding-left, padding-right์„ ๋‹ค๋ฅด๊ฒŒ ์ค˜์•ผ ํ•˜๊ฒŒ ๋•Œ๋ฌธ์— hasIcon, default๋กœ ๋‚˜๋ˆ„๊ณ , ํ•ด๋‹นํ•˜๋Š” size ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด ์Šคํƒ€์ผ์„ ์ง€์ •ํ•ด ์คฌ์—ˆ๋‹ค. ์‚ฌ์ด์ฆˆ๋Š” ๋ฐ›์•„์„œ ์Šคํƒ€์ผ์„ ์ฃผ๋Š” ๊ฒŒ ์ข‹์„์ง€, height ๊ฐ’์„ prop์œผ๋กœ ๋ฐ›์•„์„œ ์Šคํƒ€์ผ์„ ์œ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒŒ ์ข‹์„์ง€ ๊ณ ๋ฏผ์ด๋‹ค. height์œผ๋กœ ๋†’์ด๋งŒ ์ง€์ •ํ•˜๊ณ , padding์€ ๋น„๋ก€ํ•˜๊ฒŒ ํ•˜๋ฉด ๋ ๊นŒ?

์ผ๋‹จ size์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ height์™€ padding์ด ์ง€์ •๋˜๋„๋ก ํ•ด์„œ ์•„์ด์ฝ˜ ์œ ๋ฌด์— ๋”ฐ๋ผ padding ๊ฐ’์„ ๋” ์ฃผ๋Š” ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ–ˆ๋‹ค. ๋˜‘๊ฐ™์€ ๋น„์œจ๋กœ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ•˜๋‹ค๊ฐ€ ํ•˜๋“œ ์ฝ”๋”ฉํ•œ ๊ฑฐ ๊ฐ™๋‹ค..๐Ÿฅฒ

์ฃผ์š” ์ฝ”๋“œ๋งŒ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

///...
const SIZE_SET: {
  [key in Size]: {
    paddingLeft: string | SpacingStyles;
    paddingRight: string | SpacingStyles;
  };
} = {
  sm: {
    paddingLeft: spacing.pl(3),
    paddingRight: spacing.pr(3),
  },
  md: {
    paddingLeft: spacing.pl(4),
    paddingRight: spacing.pr(4),
  },
  lg: {
    paddingLeft: spacing.pl(6),
    paddingRight: spacing.pr(6),
  },
} as const;

const HEIGHT_SIZE_SET: { [key in Size]: string } = {
  sm: '2rem',
  md: '3rem',
  lg: '4rem',
} as const;

const FONT_SIZE_SET: { [key in Size]: string } = {
  sm: '.875rem',
  md: '1rem',
  lg: '1.125rem',
} as const;
///...

const Input = (
  {
    type = 'text',
    leftIcon,
    rightIcon,
    variant,
    helperText,
    inputSize = 'md',
    radius = 'default',
    iconSize,
    ...props
  }: InputProps,
  ref: ForwardedRef<HTMLInputElement>,
) => {
  const borderColor = getColorStyle(variant);
  const helperTextColor = getColorStyle(variant);
  const hasLeftIcon = !!leftIcon;
  const hasRightIcon = !!rightIcon;
  const sizeStyle = SIZE_SET[inputSize];
  let paddingLeft = sizeStyle.paddingLeft;
  let paddingRight = sizeStyle.paddingRight;

  if (hasLeftIcon) {
    paddingLeft = css`
      padding-left: calc(32px + ${iconSize ? `${iconSize}px` : '30px'});
    `;
  }

  if (hasRightIcon) {
    paddingRight = css`
      padding-right: calc(32px + ${iconSize ? `${iconSize}px` : '30px'});
    `;
  }

  return (
    <Wrapper>
      <div style={{ position: 'relative', display: 'flex', width: '100%' }}>
        {leftIcon && (
          <IconBox className="leftIcon" iconSize={iconSize}>
            {leftIcon}
          </IconBox>
        )}
        <BaseInput
          type={type}
          ref={ref}
          borderColor={borderColor}
          radius={radius}
          textSize={inputSize}
          heightSize={HEIGHT_SIZE_SET[inputSize]}
          paddingLeft={paddingLeft}
          paddingRight={paddingRight}
          {...props}
        />
        {rightIcon && (
          <IconBox className="rightIcon" iconSize={iconSize}>
            {rightIcon}
          </IconBox>
        )}
      </div>
      {helperText && (
        <HelperText
          color={helperTextColor}
          textSize={inputSize}
          heightSize={HEIGHT_SIZE_SET[inputSize]}
        >
          {helperText}
        </HelperText>
      )}
    </Wrapper>
  );
};

//...

const BaseInput = styled.input<{
  borderColor: string;
  radius: ComponentBorderKey;
  textSize: Size;
  heightSize: string;
  paddingLeft: string | SpacingStyles;
  paddingRight: string | SpacingStyles;
}>`
  height: ${({ heightSize }) => heightSize};
  font-size: ${({ textSize }) => FONT_SIZE_SET[textSize]};
  ${({ paddingLeft }) => paddingLeft};
  ${({ paddingRight }) => paddingRight};
`;

export default forwardRef(Input);
8 ์ผ์ฐจ

Breadcrumb ์ปดํฌ๋„ŒํŠธ

Breadcrumb์€ ์œ ์ €์—๊ฒŒ ์›น์‚ฌ์ดํŠธ ๋‚ด์—์„œ ํ˜„์žฌ ์œ„์น˜๋ฅผ ์‹œ๊ฐ์ ์œผ๋กœ ์•Œ๋ ค์ฃผ๋Š” ๋„ค๋น„๊ฒŒ์ด์…˜ ์š”์†Œ์ด๋‹ค. ๊ฐ ๊ฒฝ๋กœ name๊ณผ url์„ ๋‹ด์€ breadcrumbItems๋ฐฐ์—ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๋‹น ํŽ˜์ด์ง€๋Š” ์–ด๋–ค ์นดํ…Œ๊ณ ๋ฆฌ์— ์†ํ•ด์žˆ๋Š”์ง€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. Components > Breadcrumb ์ด๋Ÿฐ์‹์œผ๋กœ >๋กœ ๊ตฌ๋ถ„๋˜์–ด ํ‘œ์‹œ๋˜๊ฒŒ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด Breadcrumb ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

//next.js ์‚ฌ์šฉ์˜ˆ์‹œ
'use client';

import React from 'react';
import { usePathname } from 'next/navigation';

const paths = usePathname();
// ๊ฒฝ๋กœ name๊ณผ url์„ ๋‹ด์€ breadcrumbItems๋ฐฐ์—ด๋กœ current pathname์„ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
const breadcrumbItems = [
  { name: 'Home', url: '/' },
  { name: 'Ui', url: `${paths}` },
];
//..
<Breadcrumb
  paths={breadcrumbItems}
  containerClasses="breadcrumb-container"
  listClasses="breadcrumb-item"
  activeClasses="active"
/>;

์ง€๊ธˆ Breadcrumb ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ์€ ๊ณ ์ •์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์ด์ฆˆ๋‚˜ ๊ตฌ๋ถ„์ž๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฆฌํŒฉํ† ๋ง ํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค.

9 ์ผ์ฐจ

Tooltip ์ปดํฌ๋„ŒํŠธ

Tooltip ์ปดํฌ๋„ŒํŠธ๋Š” ํ…์ŠคํŠธ, ์•„์ด์ฝ˜, ๋ฒ„ํŠผ ๋“ฑ ํ…์ŠคํŠธ ์—†์ด ๊ทธ๋ž˜ํ”ฝ ํ˜•ํƒœ๋กœ๋งŒ ์ด๋ฃจ์–ด์ง„ ์•„์ด์ฝ˜์ด๋‚˜ ์„œ๋น„์Šค์— ๋”ฐ๋ผ ํŠน๋ณ„ํžˆ ์‚ฌ์šฉ๋˜๋Š” ๋ฒ„ํŠผ๋ช… ๋“ฑ๋“ฑ ui ์š”์†Œ์˜ ๊ธฐ๋Šฅ์„ ๋ณด์กฐ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด Tooltip ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

// ์‚ฌ์šฉ์˜ˆ์‹œ
<Tooltip message="๋ฉ”๋‰ด" direction="left" variant="info">
  <Menu />
</Tooltip>

Tooltip ์•ˆ์— ๋“ค์–ด๊ฐˆ message, Tooltip์„ ๋‚˜ํƒ€๋‚ผ ๋ฐฉํ–ฅ, Tooltip ๋ฐฐ๊ฒฝ์ƒ‰์„ ๋‚˜ํƒ€๋‚ด์ค„ variant ์†์„ฑ์„ ์ „๋‹ฌํ•ด ์ค˜์•ผ ํ•œ๋‹ค.

// Tooltip ์ปดํฌ๋„ŒํŠธ
const Tooltip = (
  { children, message, variant, direction }: TooltipProps,
  ref: ForwardedRef<HTMLDivElement>,
) => {
  return (
    <Wrapper ref={ref}>
      {children}
      <TooltipContainer
        variant={variant}
        className={`tooltip ${direction}`}
        direction={direction}
      >
        {message}
      </TooltipContainer>
    </Wrapper>
  );
};

Menu ์ปดํฌ๋„ŒํŠธ(children)๋ฅผ ์ค‘์‹ฌ์œผ๋กœ TooltipContainer๋Š” direction ์†์„ฑ์— ๋”ฐ๋ผ Tooltip์˜ ๋ฐฉํ–ฅ์„ ๊ฒฐ์ •๋œ๋‹ค.

๋งˆ์šฐ์Šค ํ˜ธ๋ฒ„ ์ธํ„ฐ๋ž™์…˜์— ์˜ํ•ด ๋‚˜ํƒ€๋‚˜๋Š”๋ฐ ๋งˆ์šฐ์Šค ์žฅ์น˜๊ฐ€ ์—†์„ ํ™˜๊ฒฝ์„ ๊ณ ๋ คํ•ด์„œ ํ‚ค๋ณด๋“œ ์žฅ์น˜๋กœ๋„ ์ž‘๋™๋  ์ˆ˜ ์žˆ๋„๋ก ์ถ”๊ฐ€ํ•ด์•ผ๊ฒ ๋‹ค.

10 ์ผ์ฐจ

Menu ์ปดํฌ๋„ŒํŠธ

11 ์ผ์ฐจ

Navbar ์ปดํฌ๋„ŒํŠธ