GhostTextField

Data Input

투명 배경과 얇은 윤곽선으로만 입력 영역을 나타내는 텍스트 필드.

Usage

테두리 없는 인라인 텍스트 입력. 제목·인라인 편집 등 배경에 녹는 입력

import

import

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

API Reference

GhostTextField Props

Prop

Type

Default

cacheMeasurements

boolean

지정 안 함

className

string

지정 안 함

endAdornment

ReactNode

지정 안 함

maxRows

number

지정 안 함

minRows

number

지정 안 함

onHeightChange

(height: number, meta: TextareaHeightChangeMeta) => void

지정 안 함

size

"md" | "sm"

md

예제

기본 사용

테두리 없이 글자만 보이는 입력 — 문서 제목처럼 자리에서 바로 고쳐 쓰는 자리에 씁니다.

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

const STORY_DEFAULT_ARGS = { ...({}), ...({
    placeholder: '제목 입력...',
    size: 'md',
  }) } as ComponentProps<typeof GhostTextField>;

const GhostTextFieldDemoExampleRender = (args: ComponentProps<typeof GhostTextField>) => <GhostTextField {...args} />;

export default function GhostTextFieldDemoExample(props: Partial<ComponentProps<typeof GhostTextField>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof GhostTextField>;
  return GhostTextFieldDemoExampleRender(mergedProps);
}

상태

권한이 없어 고칠 수 없는 제목은 disabled 로 잠급니다 — 글자는 그대로 읽힙니다.

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

const STORY_DEFAULT_ARGS = { ...({}), ...({
    placeholder: '제목 입력...',
  }) } as ComponentProps<typeof GhostTextField>;

const GhostTextFieldStateGuideExampleRender = (args: ComponentProps<typeof GhostTextField>) => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 24, padding: 24, alignItems: 'flex-start' }}>
      <div>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 8 }}>Inactive</p>
        <GhostTextField {...args} placeholder="제목 입력..." />
      </div>
      <div>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 8 }}>Hover</p>
        <GhostTextField {...args} placeholder="제목 입력..." _containerId="pseudo-hover" />
      </div>
      <div>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 8 }}>Focus</p>
        <GhostTextField {...args} defaultValue="5형식 문장" _containerId="pseudo-focus" autoFocus />
      </div>
      <div>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 8 }}>Active</p>
        <GhostTextField {...args} defaultValue="5형식 문장" />
      </div>
      <div>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 8 }}>Active Hover</p>
        <GhostTextField {...args} defaultValue="5형식 문장" _containerId="pseudo-hover" />
      </div>
      <div>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 8 }}>Disabled</p>
        <GhostTextField {...args} defaultValue="비활성 상태" disabled />
      </div>
      <div>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 8 }}>Read-only</p>
        <GhostTextField {...args} defaultValue="읽기 전용" readOnly />
      </div>
    </div>
  );

export default function GhostTextFieldStateGuideExample(props: Partial<ComponentProps<typeof GhostTextField>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof GhostTextField>;
  return GhostTextFieldStateGuideExampleRender(mergedProps);
}

TextStyleVariants

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

const GhostTextFieldTextStyleVariantsExample = () => {
    const samples: Array<{ textStyle: string; label: string }> = [
      { textStyle: 'title-2xl', label: 'title-2xl (size=md 기본값)' },
      { textStyle: 'headline-md', label: 'headline-md (페이지 타이틀급)' },
      { textStyle: 'title-md-medium', label: 'title-md-medium (질문 타이틀)' },
      { textStyle: 'body-lg', label: 'body-lg (섹션 제목)' },
      { textStyle: 'body-sm', label: 'body-sm (보조 설명)' },
      { textStyle: 'title-xs-medium', label: 'title-xs-medium (size=sm 기본값)' },
      { textStyle: 'caption-md', label: 'caption-md (작은 캡션)' },
    ];
    return (
      <div
        style={{
          display: 'flex',
          flexDirection: 'column',
          gap: 16,
          padding: 24,
          alignItems: 'flex-start',
          minWidth: 320,
        }}
      >
        {samples.map(({ textStyle, label }) => (
          <div key={textStyle} style={{ width: '100%' }}>
            <p style={{ color: '#86878C', fontSize: 12, marginBottom: 4 }}>{label}</p>
            <GhostTextField textStyle={textStyle} defaultValue="텍스트 스타일 미리보기" />
          </div>
        ))}
      </div>
    );
  };

export default GhostTextFieldTextStyleVariantsExample;

MaxLength

import { useState } from 'react';
import { GhostTextField as GhostTextField } from '@mildang/design-system/GhostTextField';

const GhostTextFieldMaxLengthExample = () => {
    const MAX = 20;
    const [value, setValue] = useState('');
    return (
      <div
        style={{
          display: 'flex',
          flexDirection: 'column',
          gap: 24,
          padding: 24,
          alignItems: 'flex-start',
          minWidth: 360,
        }}
      >
        <div style={{ width: '100%' }}>
          <p style={{ color: '#86878C', fontSize: 12, marginBottom: 4 }}>
            controlled — 입력에 따라 카운터 갱신, {MAX}자 도달 시 입력 차단
          </p>
          <GhostTextField
            placeholder="제목을 입력하세요"
            maxLength={MAX}
            value={value}
            onChange={(e) => setValue(e.target.value)}
            endAdornment={
              <span style={{ color: value.length >= MAX ? '#E5484D' : '#86878C', fontSize: 12 }}>
                {value.length}/{MAX}
              </span>
            }
          />
        </div>
        <div style={{ width: '100%' }}>
          <p style={{ color: '#86878C', fontSize: 12, marginBottom: 4 }}>
            uncontrolled — defaultValue + maxLength만 사용 (카운터 없음)
          </p>
          <GhostTextField defaultValue="네이티브 maxLength 동작" maxLength={10} />
        </div>
      </div>
    );
  };

export default GhostTextFieldMaxLengthExample;

Multiline

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

const STORY_DEFAULT_ARGS = { ...({}), ...({}) } as ComponentProps<typeof GhostTextField>;

const GhostTextFieldMultilineExampleRender = (args: ComponentProps<typeof GhostTextField>) => (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        gap: 24,
        padding: 24,
        alignItems: 'flex-start',
        minWidth: 480,
      }}
    >
      <div style={{ width: '100%' }}>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 4 }}>minRows=1, maxRows=∞ (기본값)</p>
        <GhostTextField {...args} placeholder="줄바꿈하면 자동으로 늘어납니다" />
      </div>
      <div style={{ width: '100%' }}>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 4 }}>minRows=3</p>
        <GhostTextField
          {...args}
          minRows={3}
          textStyle="body-lg"
          placeholder="시작부터 3줄 높이를 유지합니다"
        />
      </div>
      <div style={{ width: '100%' }}>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 4 }}>maxRows=4 (초과 시 스크롤)</p>
        <GhostTextField
          {...args}
          maxRows={4}
          textStyle="body-lg"
          defaultValue={'1번 줄\n2번 줄\n3번 줄\n4번 줄\n5번 줄 (스크롤)\n6번 줄 (스크롤)'}
        />
      </div>
      <div style={{ width: '100%' }}>
        <p style={{ color: '#86878C', fontSize: 12, marginBottom: 4 }}>긴 텍스트 자동 줄바꿈 (word-break)</p>
        <GhostTextField
          {...args}
          textStyle="body-sm"
          defaultValue="본 설문은 경기온라인학교에서 운영 중인 콘텐츠 강좌에 참여하기 앞서 학습자의 사전 학습 수준 및 기대 사항을 파악하여 더 나은 강좌 운영을 위해 실시하는 것이오니 솔직하고 성실한 답변 부탁드립니다."
        />
      </div>
    </div>
  );

export default function GhostTextFieldMultilineExample(props: Partial<ComponentProps<typeof GhostTextField>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof GhostTextField>;
  return GhostTextFieldMultilineExampleRender(mergedProps);
}

WithEndAdornment

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

const STORY_DEFAULT_ARGS = { ...({}), ...({}) } as ComponentProps<typeof GhostTextField>;

const GhostTextFieldWithEndAdornmentExampleRender = (args: ComponentProps<typeof GhostTextField>) => (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        gap: 24,
        padding: 24,
        alignItems: 'flex-start',
        minWidth: 360,
      }}
    >
      <GhostTextField
        {...args}
        maxLength={20}
        defaultValue="끝장식 카운터"
        endAdornment={<span style={{ color: '#86878C', fontSize: 12 }}>6/20</span>}
      />
      <GhostTextField
        {...args}
        textStyle="body-lg"
        minRows={3}
        defaultValue={'여러 줄 입력에서도\n끝장식은 마지막 줄 우측에 정렬됩니다.'}
        endAdornment={<span style={{ color: '#86878C', fontSize: 12 }}>flex-end</span>}
      />
    </div>
  );

export default function GhostTextFieldWithEndAdornmentExample(props: Partial<ComponentProps<typeof GhostTextField>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof GhostTextField>;
  return GhostTextFieldWithEndAdornmentExampleRender(mergedProps);
}