Pattern

Foundation

선·점·격자 같은 반복 요소로 형태적 구분을 주는 패턴.

Usage

색상만으로 구분하기 어려운 영역에 선·점·격자 패턴을 더해 접근성을 높일 때 사용한다. 차트·상태 영역처럼 같은 색조 안에서도 범주를 형태로 구분해야 할 때 사용한다.

import

import

import { Pattern } from '@mildang/design-system/Pattern';

예제를 복사해 쓸 때 필요한 준비

@mildang/styled-system 은 이 저장소에서 Panda 가 생성하는 산출물이다. 저장소 안에서는 turbo run ship 이후 쓸 수 있고, 패키지 소비자는 자기 Panda 산출물이나 다른 레이아웃 수단으로 바꿔야 한다.

API Reference

Pattern Props

Prop

Type

Default

type
필수

"horizontal" | "vertical" | "diagonal" | "diagonalReverse" | "crossDot" | "dot" | "square" | "cross" | "grid" | "gridBold"

지정 안 함

backColor

string

transparent

frontColor

string

neutral.border.high

opacity

"10" | "20" | "40" | "30" | "50" | "60" | "70" | "80" | "90" | "100" | "disable"

100

panda

SystemStyleObject

지정 안 함

size

"sm" | "md" | "lg"

md

spacing

number

1

사용 가이드

권장

  • 배경색과 패턴색의 대비를 확인하고 색상 외 구분 단서로 사용한다.

지양

  • 장식만을 위해 본문 전체에 강한 패턴을 반복해 가독성을 낮추지 않는다.

예제

패턴 유형

다섯 패턴 유형과 세 크기를 나란히 비교한다. frontColor·backColor 를 비우면 각각 neutral 테두리색과 투명으로 그려진다.

코드

import type { ComponentProps } from 'react';
import { Pattern as Pattern } from '@mildang/design-system/Pattern';
import { css } from '@mildang/styled-system/css';
import { type PatternVariantProps } from '@mildang/styled-system/recipes';

const boxStyle = css({
  width: '40px',
  height: '40px',
  border: '1px solid token(colors.neutral.border.base)',
  borderRadius: 4,
  boxShadow: 'core.3',
});

const patternList: {
  name: PatternVariantProps['type'];
  sizes: Partial<PatternVariantProps['size']>[];
}[] = [
  { name: 'diagonal', sizes: ['sm', 'lg'] },
  { name: 'diagonalReverse', sizes: ['sm', 'lg'] },
  { name: 'crossDot', sizes: [] },
  { name: 'dot', sizes: [] },
  { name: 'grid', sizes: [] },
  { name: 'vertical', sizes: [] },
  { name: 'horizontal', sizes: [] },
  { name: 'cross', sizes: [] },
  { name: 'square', sizes: ['sm', 'md', 'lg'] },
];

const sizeList = ['sm', 'md', 'lg'] as PatternVariantProps['size'][];

const STORY_DEFAULT_ARGS = { ...({}), ...({
    backColor: 'neutral.surface.low',
    frontColor: 'positive.text.base',
    opacity: '100',
    spacing: 1,
    size: 'sm',
  }) } as ComponentProps<typeof Pattern>;

const PatternAllStoriesExampleRender = (args: ComponentProps<typeof Pattern>) => (
    <table style={{ borderCollapse: 'collapse', width: 'auto' }}>
      <thead>
        <tr>
          <th style={{ border: '1px solid #ddd', padding: 4 }}>패턴명</th>
          {sizeList.map((size) => (
            <th key={size} style={{ border: '1px solid #ddd', padding: 4 }}>
              {size}
            </th>
          ))}
        </tr>
      </thead>
      <tbody>
        {patternList.map((pattern) => (
          <tr key={pattern.name}>
            <td style={{ border: '1px solid #ddd', padding: 4 }}>{pattern.name}</td>
            {sizeList.map((size) => (
              <td key={size} style={{ border: '1px solid #ddd', padding: 4 }}>
                {pattern.sizes.length === 0 && size === 'sm' && (
                  <Pattern {...args} type={pattern.name} className={boxStyle} />
                )}
                {pattern.sizes.includes(size) && (
                  <Pattern {...args} type={pattern.name} size={size} className={boxStyle} />
                )}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );

export default function PatternAllStoriesExample(props: Partial<ComponentProps<typeof Pattern>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof Pattern>;
  return PatternAllStoriesExampleRender(mergedProps);
}

Demo

import type { ComponentProps } from 'react';
import { Pattern as Pattern } from '@mildang/design-system/Pattern';
import { css } from '@mildang/styled-system/css';

const boxStyle = css({
  width: '40px',
  height: '40px',
  border: '1px solid token(colors.neutral.border.base)',
  borderRadius: 4,
  boxShadow: 'core.3',
});

const STORY_DEFAULT_ARGS = { ...({}), ...({
    type: 'diagonal',
    backColor: 'neutral.surface.low',
    frontColor: 'positive.fill.base',
    opacity: '100',
    spacing: 1,
    size: 'sm',
  }) } as ComponentProps<typeof Pattern>;

const PatternDemoExampleRender = (args: ComponentProps<typeof Pattern>) => <Pattern {...args} className={boxStyle} />;

export default function PatternDemoExample(props: Partial<ComponentProps<typeof Pattern>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof Pattern>;
  return PatternDemoExampleRender(mergedProps);
}

RecipeOnly

코드

import type { ComponentProps } from 'react';
import { Pattern as Pattern } from '@mildang/design-system/Pattern';
import { type Token, token } from '@mildang/styled-system/tokens';
import { type CSSProperties } from 'react';
import { css, cx } from '@mildang/styled-system/css';
import { pattern } from '@mildang/styled-system/recipes';

const STORY_DEFAULT_ARGS = { ...({}), ...({
    type: 'diagonal',
    size: 'sm',
    backColor: 'critical.fill.base',
    frontColor: 'neutral.surface.low',
    opacity: '100',
    spacing: 1,
  }) } as ComponentProps<typeof Pattern>;

const PatternRecipeOnlyExampleRender = (args: ComponentProps<typeof Pattern>) => {
    const { backColor, frontColor, opacity, spacing, ...rest } = args;

    return (
      <div
        style={
          {
            '--pattern-back-color': token(`colors.${backColor}` as Token),
            '--pattern-front-color': token(`colors.${frontColor}` as Token),
            '--pattern-spacing': `${spacing}px`,
            '--pattern-opacity': token(`opacity.${opacity}` as Token),
          } as CSSProperties
        }
        className={cx(
          pattern({ ...rest }),
          css({
            width: '80px',
            height: '80px',
            boxShadow: 'core.5',
            clipPath:
              'path("M40 15 C40 5, 25 0, 20 10 C15 0, 0 5, 0 15 C0 30, 20 40, 20 40 C20 40, 40 30, 40 15 Z")',
          }),
        )}
      />
    );
  };

export default function PatternRecipeOnlyExample(props: Partial<ComponentProps<typeof Pattern>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof Pattern>;
  return PatternRecipeOnlyExampleRender(mergedProps);
}