feat(frontend): 메일 쓰기 서식 편집기와 입력칸 포커스 통일

메일 쓰기 화면은 입력칸마다 포커스 모양이 달랐고, 본문은 서식 없는 글만 쓸 수 있었다.

- 글자 입력 행(받는 사람·참조·숨은참조·제목·본문)의 포커스를 아래 선 하나(.compose-field)로 통일했다
- 본문을 TipTap 서식 편집기로 바꿨다 — 글꼴·크기·굵게·색·목록·링크·정렬·들여쓰기·인용·표·가로줄, 단축키,
  좁은 폭에서 묶음째 접는 툴바. 편집기는 쓰기 화면에서 따로 불러온다(지연 로딩)
- 보낼 때는 기본 글꼴(맑은 고딕) div 와 인라인 style 의 HTML 에 텍스트 대체 본문을 함께 보낸다 (여러 칸 공백은 nbsp, 탭은 8칸 자리까지)
- 붙여 넣은 글·원문 인용은 서버 정화와 같은 값 형식만 읽는다 — 편집기에서 숨은 글이 받는 사람에게 보이지 않게
- 답장·전달 인용은 "원본 메일" 머리와 함께 서식째 옮긴다. 초안은 내 글 몫 5%를 남기고, 보내기 직전에 다시 재서 인용을 줄인다
- 본문에 붙여 넣거나 끌어다 놓은 이미지·파일은 첨부로 올린다 — 화면 어디에 놓아도 (브라우저가 파일을 열어 쓰던 메일을 잃지 않게)

의존성: @tiptap/* 3.31.4 (MIT 무료 패키지만, 모두 같은 판으로 고정)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 07:49:40 +09:00
parent 8fc73aa541
commit f77179a508
63 changed files with 8310 additions and 387 deletions
+15
View File
@@ -48,6 +48,21 @@ a:hover {
outline-offset: var(--focus-ring-offset);
}
/*
* 글자 입력칸 포커스 — 한 가지 규칙 (디자인 README "메일 쓰기 · 글자 입력칸 포커스")
* 받는 사람·참조·숨은참조 행, 제목 행, 본문 편집 영역에 .compose-field 를 붙인다.
* 쓰는 곳에 커서가 있으면 그 행의 아래 1px 선이 2px 브랜드색이 된다 (선 색 + 안쪽 1px — 높이가 변하지 않는다).
* 행 안의 버튼(토큰 ✕ · "참조 · 숨은참조")에 포커스가 가면 버튼 고리만 보이고 선은 회색 그대로다.
*/
.compose-field:has(:is(input, .ProseMirror):focus) {
border-bottom-color: var(--color-brand);
box-shadow: inset 0 calc(var(--border-width) * -1) 0 var(--color-brand);
}
.compose-field :is(input, .ProseMirror):focus-visible {
outline: none;
}
/* 화면에는 숨기고 스크린리더에는 읽힌다 (안 읽음·준비 중 같은 상태 전달용) */
.visually-hidden {
position: absolute;
+24
View File
@@ -160,4 +160,28 @@
--content-toolbar-start: calc(var(--content-inline) - var(--toolbar-button-inline));
/* 744px — 쓰기 본문 입력칸 = 글줄 680 + 좌우 여백 */
--compose-body-max-width: calc(var(--content-measure) + var(--content-inline) * 2);
/*
* ── 메일 쓰기 서식 편집기 (디자인 README "메일 쓰기", 2026-10-27 확정) ──
* 아래 네 크기는 클릭 영역 44px 기준의 의도된 예외다 — 사용자 확정 (디자인 README "디자인 원칙").
* 툴바 아이콘 버튼 40×44 · 메뉴 항목 높이 40 · 색 견본 칸 40×40 · 표 고르기 칸 22(간격 3, 키보드는 화살표)
*/
--size-editor-tool: 2.5rem; /* 40px — 툴바 아이콘 버튼 폭 (높이는 --size-touch 44px) · 밀도 예외 */
--size-editor-menu-item: 2.5rem; /* 40px — 메뉴 항목 높이 · 밀도 예외 */
--size-editor-swatch-cell: 2.5rem; /* 40px — 색 견본 칸 · 밀도 예외 */
--size-editor-table-cell: 1.375rem; /* 22px — 표 고르기 격자 칸 · 밀도 예외 */
--editor-table-cell-gap: 0.1875rem; /* 3px */
--size-editor-swatch: 1.625rem; /* 26px — 견본 안에 보이는 색 */
--size-editor-font-button: 6.75rem; /* 108px — 글꼴 단추 */
--size-editor-size-button: 3.5rem; /* 56px — 글자 크기 단추 */
--size-editor-toolbar: 3.25rem; /* 52px — 툴바 높이 (위아래 4) */
--size-editor-body-min: 18.75rem; /* 300px — 본문 편집 영역의 최소 높이 (편집기를 불러오는 동안의 자리도 같다) */
--editor-toolbar-inline: 1.25rem; /* 20px — 툴바 좌우 여백. 버튼 안 12 를 더하면 첫 아이콘이 32px 선 */
--color-editor-pressed-hover: #d5ebed; /* 켜진 버튼에 마우스를 올렸을 때 */
--color-quote-bar: #d0d5dd; /* 원문 인용 막대 — 포커스 선(브랜드색)과 겹치지 않게 회색 */
--color-drop-surface: rgba(243, 248, 248, 0.94); /* 끌어다 놓는 동안의 덮개 */
/* 본문 기본 글꼴 — 맑은 고딕 스택. 보내는 HTML 의 글꼴(shared/constants/mail-editor.ts MAIL_BODY_FONT_FAMILY)과 같다 */
--font-family-mail-body: 'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif;
/* 본문 줄 간격 — 보내는 HTML 의 줄 간격(shared/constants/mail-editor.ts MAIL_BODY_LINE_HEIGHT)과 같다 */
--line-height-mail-body: 1.75;
}