JS Design System v0.6

Text Field

한 줄 텍스트를 입력합니다. 라벨·도움말·오류 메시지가 하나의 필드 단위로 묶입니다.

1. Default / Error

오류 시 .error 를 필드에 붙이고 help 를 오류 메시지로 바꿉니다. 원인과 해결 방법을 함께 씁니다.

IPv4 형식
올바른 IPv4 형식이 아닙니다. 예: 10.0.0.12

2. Size

sm 36 · md 44 · lg 52. 버튼과 같은 높이로 나란히 배치합니다.

3. Prefix / Suffix / Counter

단위·접두어는 .affix 컨테이너 안에 span 으로. 글자 수 제한은 .counter.

일
https://
12 / 80

4. Textarea

여러 줄 입력. 높이는 세로 리사이즈 허용, 최소 96px.

감사 로그에 기록됩니다

5. Disabled / Read-only

Disabled 는 값을 바꿀 수도 복사할 수도 없을 때, Read-only 는 참조만 할 때.

자동 생성

Props

HTML 에서는 클래스와 속성으로, React(@jiran/ds-react)에서는 같은 이름의 prop(variant · size …)으로 변형·상태를 지정합니다.

Prop / ClassType · ValuesDefaultDescription
.fieldcontainer—label + input(+ .help) 묶음. 폼 안에서 min-width 해제
sizesm | (md) | lgmd입력 높이 36 / 44 / 52
.errorbooleanfalse보더 danger, help 를 오류 메시지로. input 에 aria-invalid
.affixwrapper—접두어/접미어 span 과 input 을 감싸는 컨테이너
.counterelement—글자 수 표시. .row 안에서 라벨 우측 정렬
disabled / readonlyattribute—비활성 / 읽기 전용(배경 subtle)

Usage

React: @jiran/ds-react 패키지를 설치하고 style.css 를 한 번 import 하면 위 React 탭 코드를 그대로 쓸 수 있습니다(React Package). HTML: assets/style.css 를 연결하고(일부만 필요하면 아래 컴포넌트 CSS 복사), 동작이 필요하면 assets/ds.js 를 함께 넣습니다 — 이 페이지의 프리뷰가 그 스크립트로 동작합니다. 색은 전부 토큰(var(--accent) 등)을 참조하므로 --accent-* 만 제품 컬러로 바꾸면 됩니다.

React @jiran/ds-react

npm i @jiran/ds-react

// main.tsx — 앱 진입점에서 한 번
import "@jiran/ds-react/style.css";

// 컴포넌트
import { Field, TextField, TextArea } from "@jiran/ds-react";

HTML

<!-- 1) 토큰 + 전체 컴포넌트 스타일 한 번에 연결 -->
<link rel="stylesheet" href="assets/style.css">
<!-- 동작(드롭다운·탭·달력·표 정렬/선택·토스트 등) — 순수 JS 한 파일. React 제품은 불필요 -->
<script src="assets/ds.js" defer></script>

<!-- 2) 또는 아래 "Component CSS" 만 프로젝트 CSS 에 붙이고,
        :root 토큰은 Foundations › Design Token 에서 복사 -->

Component CSS .field

/* JS Design System v0.6 · .field · 토큰(var(--*))은 assets/style.css :root 참고 */
.field{display:flex;flex-direction:column;gap:6px;min-width:260px;font-size:14px}
.field label{font-weight:600}
.field label em{color:var(--danger-text);font-style:normal;margin-left:2px}
.field input,.field textarea{height:44px;border:1px solid var(--border-strong);border-radius:var(--radius-md);padding:0 14px;font:inherit;font-size:14px;background:var(--bg-surface);color:var(--text-primary);width:100%;transition:border-color var(--motion-fast)}
.field textarea{height:auto;min-height:96px;padding:10px 14px;resize:vertical;line-height:1.5}
.field input::placeholder,.field textarea::placeholder{color:var(--text-disabled)}
.field input:hover,.field textarea:hover{border-color:var(--border-strong)}
.field input:focus,.field textarea:focus-within{border-color:var(--border-focus)}
.field input:disabled,.field textarea:disabled{background:var(--bg-panel);color:var(--text-disabled);cursor:not-allowed}
.field input:read-only{background:var(--bg-subtle)}
.field .help{color:var(--text-tertiary);font-size:12px}
.field.error input,.field.error textarea,.field.error .affix{border-color:var(--danger)}
.field.error .help{color:var(--danger-text)}
.field.sm input{height:36px;font-size:12px;padding:0 12px}
.field.lg input{height:52px;font-size:16px;padding:0 16px}
.field .affix{display:flex;align-items:center;gap:8px;height:44px;padding:0 12px;border:1px solid var(--border-strong);border-radius:var(--radius-md);background:var(--bg-surface)}
.field .affix input{border:0;height:auto;padding:0;flex:1;background:transparent;outline:0;min-width:0}
.field .affix:focus-within{border-color:var(--border-focus)}
.field .affix span{color:var(--text-tertiary);font-size:12px;white-space:nowrap}
.field .counter{margin-left:auto;font-size:12px;color:var(--text-tertiary)}
.field .row{display:flex;justify-content:space-between;align-items:baseline}
.form .form-row .field{min-width:0}
.form .field{min-width:0}