Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/conventions/component-convention.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ interface RentalItemCardProps {
| `caption1` | `regular` | 12px / Regular | Caption 1/Regular |
| `caption2` | `medium` | 11px / Medium | Caption 2/Medium |

- **입력칸(`<input>`)도 `Typography`로 그린다**: `Typography`는 `as`로 태그를 바꿀 수 있어서 `<Typography as="input" variant="body1" weight="regular" color="semantic.label.normal" value={…} onChange={…} />`처럼 쓰면 입력칸이 WDS 글자 스타일을 그대로 받는다. `text-[14px]`처럼 값을 박지 않는다. placeholder 색만 `placeholder:text-label-assistive`로 준다. iOS 입력칸 자동 확대는 글자 크기가 아니라 `index.html`의 viewport 설정(iOS 전용 `maximum-scale=1`)으로 막으므로 Figma 크기 그대로 둔다.
- **예외**: 서드파티 라이브러리가 `className` 문자열만 받아서 자기 DOM에 그대로 꽂는 자리(예: `@ncdai/react-wheel-picker`의 `classNames` prop)는 `Typography`로 감쌀 수 없다 — 이럴 땐 Tailwind `text-[17px]` 같은 값을 그대로 쓰되, 어느 Figma 타입 스타일을 옮긴 값인지 주석을 남긴다(`BililgeRentalSheet.tsx`의 `WHEEL_CLASS_NAMES` 참고).

- Stream 자체 이미지·아이콘(일러스트, 물품 아이콘 등)은 `download_assets`로 받아 `src/assets/`에 커밋한다. Figma asset URL은 **7일 후 만료**되므로 절대 코드에 그대로 참조하지 않는다.
Expand Down
4 changes: 2 additions & 2 deletions docs/conventions/wds-component-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ hex를 하드코딩하지 않고 `index.css`의 색상 토큰을 그대로 참
- 단답형(50자)도 같은 `TextArea`를 쓴다(Figma 텍스트 입력 예시 `1133:43105`의 디자이너 메모).
- **`Action Area/Action Area` → `ActionArea background` + `ActionAreaButton`**: `background`를 켜면 `::before`가 영역 위로 `margin-y`(20px)만큼 더 올라가 그라데이션 마스크로 스크롤 내용을 흐리게 덮는다(Figma `Gradient/Solid`와 일치). `divider`는 기본값이 `true`지만 `extra` 모드에서만 선을 그려서 일반 모드에는 영향 없다. Figma Action Area(110px = 위 20 + 버튼 56 + 아래 34)는 버튼 아래가 iOS **Bottom Safe Area까지 합쳐 34px**인데 WDS `ActionArea`는 아래 padding 20px만 줘서, 모자란 **14px**을 `bg-background-elevated-normal` div로 따로 붙였다(`BottomSheet`에서 14px을 더한 것과 같은 이유). 처음엔 Safe Area 34px을 통째로 더해서 버튼 아래가 54px로 벌어졌었다 — ActionArea 자체 padding과 겹치는지 먼저 확인한다. 이때 `--color-background-elevated-normal`(`--semantic-background-elevated-normal` 별칭) 토큰을 추가했다.
- **Action Area 메인 버튼 높이**: `ActionAreaButton`(`main`)은 항상 `Button size="large"`(padding `12px 28px` → **48px**)로 그리는데, Figma `┗ Main Action`은 padding `16px 28px`(**56px**)이다. WDS에 56px 크기가 없어서 `sx={{ paddingBlock: "16px" }}`로 세로 padding만 맞췄다(`ActionAreaButton`은 `props.sx`를 내부 `Button` 스타일 맨 뒤에 붙여서 덮어쓰기가 된다). 빌릴게 대여 바텀시트 Figma(`1422:57205`)의 "대여 신청하기" 버튼도 같은 56px 스펙이지만, `BililgeRentalSheet.tsx`는 아직 `sx` 없이 48px로 렌더링된다(위 "빌릴게 대여 바텀시트" 절의 "정확히 일치" 기록은 높이까지는 대조하지 않은 것으로 보인다).
- **기타(직접 입력) 입력칸은 WDS가 아니라 plain `<input>`**: Figma `Other Option`(`1658:183954`)은 체크박스 아래에 밑줄만 있는 입력칸이라, WDS `TextField`(배경·테두리·12px radius가 있는 박스형)와 생김새가 다르다. 밑줄은 `Primary/Normal` 0.7px(에셋 SVG의 stroke로 확인, `get_variable_defs`만으로는 선 색이 안 나온다). `<input>`은 `Typography`로 감쌀 수 없는 자리라 Figma `Label 1/Normal - Regular`(14px) 값을 className에 직접 쓰고 주석을 남겼다(휠 피커와 같은 예외).
- **기타(직접 입력) 입력칸은 WDS가 아니라 plain `<input>`**: Figma `Other Option`(`1658:183954`)은 체크박스 아래에 밑줄만 있는 입력칸이라, WDS `TextField`(배경·테두리·12px radius가 있는 박스형)와 생김새가 다르다. 밑줄은 `Primary/Normal` 0.7px(에셋 SVG의 stroke로 확인, `get_variable_defs`만으로는 선 색이 안 나온다). 글자는 `Typography as="input"`으로 Figma `Label 1/Reading - Regular`(`variant="label1-reading"`, 14px·줄 높이 22px)를 받는다(`component-convention.md` 타이포그래피 참고).
- **Top Navigation 뒤로가기**: `TopNavigationButton`에는 back 전용 variant가 없어서(`'text' | 'icon'`) `variant="icon"` + `IconChevronLeft`를 `ScreenHeader variant="normal"`의 `leading`에 넣는다.
- **`Icon/Normal/Clock`, `Icon/Normal/Location`**: 위 표의 기존 매핑 재사용(`IconClock`, `IconLocation`). 색은 `get_variable_defs`로 확인한 `Label/Assistive`(`text-label-assistive`) — 옆 텍스트(`Label/Alternative`)보다 옅다.

Expand Down Expand Up @@ -571,7 +571,7 @@ A-1 본문의 `Zone Grid Row`(`2159:110823`)가 `h-px`라 `위쪽 칸/아래쪽
| padding | medium 12 / small 8 (사방 동일) | 가로 12 · 세로 8 (높이 40) |
| 지움 버튼 | 입력창에 **포커스가 있을 때만** 표시 | 검색 완료 화면에서 포커스 없이도 표시 |

내부를 오버라이드해야 맞출 수 있어서 `src/features/search/components/SearchField.tsx`를 로컬로 만들었다. `<input>`은 `Typography`로 감쌀 수 없어 Body 1/Regular(16px) 값을 className에 직접 썼다(행사 신청 폼의 기타 입력칸과 같은 예외).
내부를 오버라이드해야 맞출 수 있어서 `src/features/search/components/SearchField.tsx`를 로컬로 만들었다. 입력칸 글자는 `Typography as="input"`으로 Body 1/Regular(`variant="body1"`)를 받는다.

### 검색 입력은 `useScreenHeader`(헤더 슬롯)에 넣지 않는다

Expand Down
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
/>
<!-- iOS는 focus된 입력칸 글자가 16px 미만이면 화면을 자동 확대하고, PWA에서는 그 배율이
돌아오지 않는다. maximum-scale=1은 그 자동 확대를 막는다(Safari는 이 값으로 사용자의
두 손가락 확대까지 막지는 않는다). Android Chrome은 이 값으로 사용자 확대가 막혀 접근성이
나빠지므로 iOS(iPadOS 포함)에서만 붙인다. 입력칸 글자는 Figma 크기 그대로 둔다. -->
<script>
if (
/iPad|iPhone|iPod/.test(navigator.userAgent) ||
(navigator.userAgent.includes("Macintosh") && navigator.maxTouchPoints > 1)
) {
const viewport = document.querySelector('meta[name="viewport"]');
viewport.content += ", maximum-scale=1";
}
</script>
<title>stream-client</title>
<link rel="preconnect" href="https://cdn.jsdelivr.net" />
<link
Expand Down
12 changes: 8 additions & 4 deletions src/features/chat/components/ChatInput.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Typography } from "@wanteddev/wds";
import { IconArrowUp } from "@wanteddev/wds-icon";
import { forwardRef } from "react";

Expand All @@ -12,8 +13,7 @@ interface ChatInputProps {
// 비활성 회색(#e1e2e4) 전송 버튼)와 state=Active(nodeId 1770:61488, 입력 있음: 검정 텍스트 +
// 파란(primary) 전송 버튼)를 입력값 유무로 토글한다. WDS `TextField`는 box-shadow +
// backdrop-blur(32px)가 기본이라 Figma의 flat 배경(그림자 없음)과 달라 재사용하지 않는다.
// 텍스트 스타일(15px/0.0096em)은 WDS Typography의 body2 값을 그대로 따랐다 — Typography
// 컴포넌트 자체는 자기 태그를 렌더링해서 네이티브 input에는 못 씌운다.
// 텍스트는 Figma body2라 Typography를 `as="input"`으로 렌더해 WDS 글자 스타일을 받는다.
// disabled(코드리뷰 지적 반영): 봇 응답을 기다리는 동안 또 보내면 앞선 응답 타이머가 취소돼
// 그 메시지에 대한 응답이 영영 안 온다 — 응답이 올 때까지 입력 자체를 막는다.
const ChatInput = forwardRef<HTMLInputElement, ChatInputProps>(
Expand All @@ -28,13 +28,17 @@ const ChatInput = forwardRef<HTMLInputElement, ChatInputProps>(
onSubmit();
}}
>
<input
className="min-w-0 flex-1 bg-transparent text-[0.9375rem] text-label-normal leading-[1.375rem] tracking-[0.0096em] placeholder:text-label-assistive focus:outline-none"
<Typography
as="input"
className="min-w-0 flex-1 bg-transparent placeholder:text-label-assistive focus:outline-none"
color="semantic.label.normal"
disabled={disabled}
onChange={(event) => onChange(event.target.value)}
placeholder="Stream AI에게 무엇이든 물어보세요"
ref={ref}
value={value}
variant="body2"
weight="regular"
/>
<button
aria-label="전송"
Expand Down
12 changes: 8 additions & 4 deletions src/features/events/components/EventsQuestionField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,13 @@ function EventsQuestionField({
</label>
</div>
{isOtherChecked && (
// <input>이라 Typography로 감쌀 수 없는 자리 — Figma "Label 1/Normal - Regular"(14px)와
// 밑줄(Primary/Normal 0.7px)을 그대로 옮긴 값이다.
<input
// Figma "Label 1/Reading - Regular" + 밑줄(Primary/Normal 0.7px). 입력칸도 Typography를
// `as="input"`으로 렌더해 글자 스타일을 WDS에서 받는다.
<Typography
aria-label={`${question.title} 기타 내용`}
className="w-full border-primary border-b-[0.7px] pb-0.5 text-[14px] text-label-normal leading-[1.571] outline-none placeholder:text-label-assistive"
as="input"
className="w-full border-primary border-b-[0.7px] pb-0.5 outline-none placeholder:text-label-assistive"
color="semantic.label.normal"
maxLength={EVENTS_OTHER_MAX_LENGTH}
onChange={(event) =>
onAnswerChange({
Expand All @@ -155,6 +157,8 @@ function EventsQuestionField({
}
placeholder="기타 내용을 입력해 주세요."
value={choiceAnswer.otherText}
variant="label1-reading"
weight="regular"
/>
)}
</div>
Expand Down
12 changes: 8 additions & 4 deletions src/features/search/components/SearchField.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Typography } from "@wanteddev/wds";
import { IconCircleCloseFill, IconSearch } from "@wanteddev/wds-icon";
import type { Ref } from "react";

Expand All @@ -17,8 +18,7 @@ interface SearchFieldProps {
// - 지움 버튼이 입력창에 포커스가 있을 때만 보이는데 Figma 검색 완료 화면은 포커스 없이도 보인다
// 내부를 오버라이드해야 맞출 수 있어서(컨벤션상 금지) 로컬로 짰다.
//
// `<input>`은 Typography로 감쌀 수 없는 자리라 Figma `Body 1/Normal - Regular`(16px, 줄높이 1.5,
// 자간 0.0912px) 값을 className에 직접 썼다(행사 신청 폼의 기타 입력칸과 같은 예외).
// 입력칸 글자는 Figma `Body 1/Normal - Regular`라 Typography를 `as="input"`으로 렌더해 WDS에서 받는다.
function SearchField({
value,
onChange,
Expand All @@ -36,16 +36,20 @@ function SearchField({
onSubmit();
}}
>
<input
<Typography
aria-label="검색어"
as="input"
autoComplete="off"
className="min-w-0 flex-1 bg-transparent text-base text-label-normal leading-6 tracking-[0.0912px] outline-none placeholder:text-label-assistive"
className="min-w-0 flex-1 bg-transparent outline-none placeholder:text-label-assistive"
color="semantic.label.normal"
enterKeyHint="search"
onChange={(event) => onChange(event.target.value)}
placeholder="검색어를 입력하세요"
ref={inputRef}
type="text"
value={value}
variant="body1"
weight="regular"
/>
{hasValue ? (
<button
Expand Down