generated from ttipo/project-base
docs: 서식 본문 계약과 메일 쓰기 편집기 디자인
- 계약 2절: 서식 본문(bodyHtml)의 허용 목록·값 형식·한도(VAL_001)·지문, 읽기 한도와 정화 전 검사(htmlBody null), 답장·전달 초안 길이 맞춤, 발송 JSON 4MB, 서식 본문 지문의 알려진 한계 - 디자인: 쓰기 화면 입력칸 포커스 규칙, 편집기 툴바·메뉴·단축키·좁은 폭 순서·팔레트, 원문 인용, 본문 이미지 → 첨부 (캔버스 Compose·ComposeEditor 보드와 구현하며 정한 것) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,34 @@
|
||||
body{margin:0}
|
||||
a{color:#0E7C86}a:hover{color:#0A5F67}
|
||||
:focus-visible{outline:2px solid #0E7C86;outline-offset:2px}
|
||||
/* 글자 입력칸 포커스: 커서가 있는 칸의 아래 선이 2px 브랜드색 (받는 사람 · 참조 · 숨은참조 · 제목 · 본문 공통) */
|
||||
.cf:has(.cf-in:focus){border-bottom-color:#0E7C86 !important;box-shadow:inset 0 -1px 0 #0E7C86}
|
||||
.cf-in:focus,.cf-in:focus-visible{outline:none}
|
||||
/* 본문 편집기 */
|
||||
.ce p{margin:0}
|
||||
.ce ul,.ce ol{margin:0;padding-left:24px}
|
||||
.ce:empty::before{content:attr(data-placeholder);float:left;height:0;color:#667085;pointer-events:none}
|
||||
/* 툴바 버튼: 올림 · 켜짐 · 비활성 · 메뉴 열림 */
|
||||
.tb{background:transparent;color:#344054}
|
||||
.tb:hover,.tb[aria-expanded="true"]{background:#F2F4F7;color:#171C26}
|
||||
.tb[aria-pressed="true"]{background:#E3F2F3;color:#0A5F67;box-shadow:inset 0 0 0 1px #0E7C86}
|
||||
.tb[aria-pressed="true"]:hover{background:#D5EBED;color:#0A5F67}
|
||||
.tb:disabled,.tb:disabled:hover{opacity:.5;cursor:default;background:transparent;color:#344054}
|
||||
.mi{background:transparent;color:#171C26}
|
||||
.mi:hover{background:#F2F4F7}
|
||||
.mi:disabled,.mi:disabled:hover{opacity:.5;cursor:default;background:transparent}
|
||||
.sw{background:transparent}
|
||||
.sw:hover{background:#F2F4F7}
|
||||
/* 어두운 바탕(알림)에서는 강조색 고리가 묻혀 밝은 색으로 바꾼다 */
|
||||
.on-dark:focus-visible{outline-color:#9ED6DB}
|
||||
/* 좁은 폭: 쓰기 칸 폭을 보고 묶음을 정해진 순서로 더보기에 옮긴다 (참고값 — 구현은 실제 폭을 잰다) */
|
||||
.cmp{container:cmp/inline-size}
|
||||
.mm-a,.mm-b,.mm-d,.mm-e,.mm-f{display:none !important}
|
||||
@container cmp (max-width:733px){.tg-a{display:none !important}.mm-a{display:flex !important}}
|
||||
@container cmp (max-width:638px){.tg-b{display:none !important}.mm-b{display:flex !important}}
|
||||
@container cmp (max-width:459px){.tg-d{display:none !important}.mm-d{display:flex !important}}
|
||||
@container cmp (max-width:364px){.tg-f{display:none !important}.mm-f{display:flex !important}}
|
||||
@container cmp (max-width:311px){.tg-e{display:none !important}.mm-e{display:flex !important}}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="min-height: 100vh; display: flex; background: #FFFFFF; color: #171C26; font-family: Pretendard, -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', system-ui, sans-serif; font-size: 13px; line-height: 1.5">
|
||||
@@ -122,7 +150,7 @@ a{color:#0E7C86}a:hover{color:#0A5F67}
|
||||
</nav>
|
||||
|
||||
<main style="flex: 999 1 560px; min-width: 0; box-sizing: border-box; display: flex; flex-direction: column">
|
||||
<form aria-labelledby="compose-title" style="flex: 1 1 auto; display: flex; flex-direction: column; max-width: 800px">
|
||||
<form class="cmp" aria-labelledby="compose-title" onDragOver="{{ onFormDragOver }}" onDragLeave="{{ onFormDragLeave }}" onDrop="{{ onFormDrop }}" style="flex: 1 1 auto; display: flex; flex-direction: column; max-width: 800px">
|
||||
|
||||
<div style="display: flex; align-items: center; gap: 8px; min-height: 52px; box-sizing: border-box; padding: 4px 18px 4px 32px; border-bottom: 1px solid #E6E8EC">
|
||||
<h1 id="compose-title" style="flex: 1 1 auto; margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -0.01em">{{ title }}</h1>
|
||||
@@ -131,7 +159,7 @@ a{color:#0E7C86}a:hover{color:#0A5F67}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 44px; box-sizing: border-box; padding: 4px 22px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<div class="cf" style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 44px; box-sizing: border-box; padding: 4px 22px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<label for="compose-to" style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">받는 사람</label>
|
||||
<div style="flex: 1 1 320px; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px">
|
||||
<sc-for list="{{ chips }}" as="chip" hint-placeholder-count="1">
|
||||
@@ -142,7 +170,7 @@ a{color:#0E7C86}a:hover{color:#0A5F67}
|
||||
</button>
|
||||
</span>
|
||||
</sc-for>
|
||||
<input id="compose-to" type="text" value="{{ toInput }}" onChange="{{ onToInput }}" onKeyDown="{{ onToKey }}" placeholder="이름 또는 메일 주소 입력 후 Enter" style="flex: 1 1 200px; min-width: 120px; min-height: 34px; border: 0; font: inherit; color: #171C26; background: transparent">
|
||||
<input id="compose-to" class="cf-in" type="text" value="{{ toInput }}" onChange="{{ onToInput }}" onKeyDown="{{ onToKey }}" placeholder="이름 또는 메일 주소 입력 후 Enter" style="flex: 1 1 200px; min-width: 120px; min-height: 34px; border: 0; font: inherit; color: #171C26; background: transparent">
|
||||
</div>
|
||||
<button type="button" onClick="{{ toggleCc }}" aria-expanded="{{ ccExpanded }}" style="min-height: 44px; padding: 0 10px; border: 0; border-radius: 8px; background: transparent; color: #0E7C86; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer">참조 · 숨은참조</button>
|
||||
</div>
|
||||
@@ -155,30 +183,423 @@ a{color:#0E7C86}a:hover{color:#0A5F67}
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ showCc }}" hint-placeholder-val="{{ false }}">
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 44px; box-sizing: border-box; padding: 4px 22px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<div class="cf" style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 44px; box-sizing: border-box; padding: 4px 22px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<label for="compose-cc" style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">참조</label>
|
||||
<input id="compose-cc" type="text" placeholder="이름 또는 메일 주소" style="flex: 1 1 320px; min-width: 0; min-height: 34px; border: 0; font: inherit; color: #171C26; background: transparent">
|
||||
<input id="compose-cc" class="cf-in" type="text" placeholder="이름 또는 메일 주소" style="flex: 1 1 320px; min-width: 0; min-height: 34px; border: 0; font: inherit; color: #171C26; background: transparent">
|
||||
</div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 44px; box-sizing: border-box; padding: 4px 22px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<div class="cf" style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 44px; box-sizing: border-box; padding: 4px 22px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<label for="compose-bcc" style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">숨은참조</label>
|
||||
<input id="compose-bcc" type="text" placeholder="이름 또는 메일 주소" style="flex: 1 1 320px; min-width: 0; min-height: 34px; border: 0; font: inherit; color: #171C26; background: transparent">
|
||||
<input id="compose-bcc" class="cf-in" type="text" placeholder="이름 또는 메일 주소" style="flex: 1 1 320px; min-width: 0; min-height: 34px; border: 0; font: inherit; color: #171C26; background: transparent">
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 44px; box-sizing: border-box; padding: 4px 22px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<div class="cf" style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 44px; box-sizing: border-box; padding: 4px 22px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<label for="compose-subject" style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">제목</label>
|
||||
<input id="compose-subject" type="text" value="{{ subject }}" onChange="{{ onSubject }}" placeholder="제목을 입력하세요" style="flex: 1 1 320px; min-width: 0; min-height: 34px; border: 0; font: inherit; font-size: 14px; font-weight: 600; color: #171C26; background: transparent">
|
||||
<input id="compose-subject" class="cf-in" type="text" value="{{ subject }}" onChange="{{ onSubject }}" placeholder="제목을 입력하세요" style="flex: 1 1 320px; min-width: 0; min-height: 34px; border: 0; font: inherit; font-size: 14px; font-weight: 600; color: #171C26; background: transparent">
|
||||
</div>
|
||||
|
||||
<textarea aria-label="본문" value="{{ body }}" onChange="{{ onBody }}" rows="13" placeholder="내용을 입력하세요" style="flex: 1 1 auto; min-height: 300px; width: 100%; max-width: 744px; box-sizing: border-box; padding: 16px 32px; border: 0; resize: vertical; font: inherit; font-size: 14px; line-height: 1.75; color: #1F2733; background: #FFFFFF"></textarea>
|
||||
<div style="flex: 1 1 auto; display: flex; flex-direction: column">
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 8px; padding: 10px 32px 14px; border-top: 1px solid #EEF0F3">
|
||||
<div role="toolbar" aria-label="본문 서식" aria-controls="compose-body" style="position: relative; z-index: 2; display: flex; align-items: center; gap: 2px; min-height: 52px; box-sizing: border-box; padding: 4px 20px; border-bottom: 1px solid #EEF0F3">
|
||||
|
||||
<div class="tg-a" style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" class="tb" disabled="{{ undoDisabled }}" aria-label="실행 취소" aria-keyshortcuts="Control+Z" title="실행 취소 (Ctrl+Z)" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 14 4 9l5-5"></path><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"></path></svg>
|
||||
</button>
|
||||
<button type="button" class="tb" disabled="{{ true }}" aria-label="다시 실행" aria-keyshortcuts="Control+Y" title="다시 실행 (Ctrl+Y)" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 14 5-5-5-5"></path><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"></path></svg>
|
||||
</button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
|
||||
<div class="tg-b" style="display: flex; align-items: center; gap: 2px">
|
||||
<div style="position: relative; display: flex">
|
||||
<button type="button" class="tb" onClick="{{ openFont }}" aria-haspopup="menu" aria-expanded="{{ fontExpanded }}" aria-label="글꼴: {{ fontName }}" title="글꼴" style="width: 108px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; padding: 0 8px 0 12px; border: 0; border-radius: 8px; font: inherit; font-weight: 500; cursor: pointer">
|
||||
<span style="flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left">{{ fontName }}</span>
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
||||
</button>
|
||||
<sc-if value="{{ fontOpen }}" hint-placeholder-val="{{ false }}">
|
||||
<div role="menu" aria-label="글꼴" onKeyDown="{{ onPopKey }}" style="position: absolute; top: 48px; left: 0; z-index: 30; width: 216px; box-sizing: border-box; padding: 6px; display: flex; flex-direction: column; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<sc-for list="{{ fontsKo }}" as="f" hint-placeholder-count="4">
|
||||
<button type="button" role="menuitemradio" aria-checked="{{ f.checked }}" class="mi" onClick="{{ f.pick }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; font-size: 14px; font-family: {{ f.family }}; text-align: left; cursor: pointer">
|
||||
<span style="flex: 1 1 auto; min-width: 0">{{ f.label }}</span>
|
||||
<sc-if value="{{ f.isBase }}" hint-placeholder-val="{{ false }}"><span style="flex: 0 0 auto; font-family: Pretendard, -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', system-ui, sans-serif; font-size: 12px; color: #667085">기본</span></sc-if>
|
||||
<sc-if value="{{ f.on }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if>
|
||||
</button>
|
||||
</sc-for>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<sc-for list="{{ fontsEn }}" as="f" hint-placeholder-count="5">
|
||||
<button type="button" role="menuitemradio" aria-checked="{{ f.checked }}" class="mi" onClick="{{ f.pick }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; font-size: 14px; font-family: {{ f.family }}; text-align: left; cursor: pointer">
|
||||
<span style="flex: 1 1 auto; min-width: 0">{{ f.label }}</span>
|
||||
<sc-if value="{{ f.on }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if>
|
||||
</button>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
<div style="position: relative; display: flex">
|
||||
<button type="button" class="tb" onClick="{{ openSize }}" aria-haspopup="menu" aria-expanded="{{ sizeExpanded }}" aria-label="글자 크기: {{ sizeLabel }}" title="글자 크기" style="width: 56px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; padding: 0 8px 0 12px; border: 0; border-radius: 8px; font: inherit; font-weight: 500; font-variant-numeric: tabular-nums; cursor: pointer">
|
||||
<span style="flex: 1 1 auto; text-align: left">{{ sizeLabel }}</span>
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
||||
</button>
|
||||
<sc-if value="{{ sizeOpen }}" hint-placeholder-val="{{ false }}">
|
||||
<div role="menu" aria-label="글자 크기" onKeyDown="{{ onPopKey }}" style="position: absolute; top: 48px; left: 0; z-index: 30; width: 132px; box-sizing: border-box; padding: 6px; display: flex; flex-direction: column; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<sc-for list="{{ sizes }}" as="s" hint-placeholder-count="8">
|
||||
<button type="button" role="menuitemradio" aria-checked="{{ s.checked }}" class="mi" onClick="{{ s.pick }}" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<span style="flex: 1 1 auto; font-size: {{ s.px }}; line-height: 1.1; font-variant-numeric: tabular-nums">{{ s.label }}</span>
|
||||
<sc-if value="{{ s.isBase }}" hint-placeholder-val="{{ false }}"><span style="font-size: 12px; color: #667085">기본</span></sc-if>
|
||||
<sc-if value="{{ s.on }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if>
|
||||
</button>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
|
||||
<div class="tg-c" style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" class="tb" onClick="{{ toggleBold }}" aria-pressed="{{ boldPressed }}" aria-label="굵게" aria-keyshortcuts="Control+B" title="굵게 (Ctrl+B)" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg>
|
||||
</button>
|
||||
<button type="button" class="tb" onClick="{{ toggleItalic }}" aria-pressed="{{ italicPressed }}" aria-label="기울임" aria-keyshortcuts="Control+I" title="기울임 (Ctrl+I)" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg>
|
||||
</button>
|
||||
<button type="button" class="tb" onClick="{{ toggleUnderline }}" aria-pressed="{{ underlinePressed }}" aria-label="밑줄" aria-keyshortcuts="Control+U" title="밑줄 (Ctrl+U)" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 3v7a6 6 0 0 0 12 0V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg>
|
||||
</button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
|
||||
<div class="tg-d" style="display: flex; align-items: center; gap: 2px">
|
||||
<div style="position: relative; display: flex">
|
||||
<button type="button" class="tb" onClick="{{ openColor }}" aria-haspopup="dialog" aria-expanded="{{ colorExpanded }}" aria-label="글자 색: {{ colorName }}" title="글자 색" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.5 14.5 12 3.5l5.5 11"></path><path d="M8.5 10.5h7"></path><rect x="4.5" y="18" width="15" height="3" rx="1" fill="{{ colorHex }}" stroke="none"></rect></svg>
|
||||
</button>
|
||||
<sc-if value="{{ colorOpen }}" hint-placeholder-val="{{ false }}">
|
||||
<div role="dialog" aria-label="글자 색" onKeyDown="{{ onPopKey }}" style="position: absolute; top: 48px; left: 0; z-index: 30; width: 186px; box-sizing: border-box; padding: 10px; display: flex; flex-direction: column; gap: 8px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<div style="display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 0 2px">
|
||||
<span style="font-size: 12.5px; font-weight: 600; color: #4A5363">글자 색</span>
|
||||
<span style="font-size: 12px; color: #667085">{{ colorName }}</span>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px">
|
||||
<sc-for list="{{ textColors }}" as="c" hint-placeholder-count="8">
|
||||
<button type="button" class="sw" onClick="{{ c.pick }}" aria-label="{{ c.name }}" aria-pressed="{{ c.pressed }}" title="{{ c.name }}" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<span style="width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; background: {{ c.hex }}; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14); color: {{ c.checkColor }}">
|
||||
<sc-if value="{{ c.on }}" hint-placeholder-val="{{ false }}"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if>
|
||||
</span>
|
||||
</button>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
<div style="position: relative; display: flex">
|
||||
<button type="button" class="tb" onClick="{{ openBg }}" aria-haspopup="dialog" aria-expanded="{{ bgExpanded }}" aria-label="배경 색: {{ bgName }}" title="배경 색" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="3.5" width="17" height="17" rx="3" fill="{{ bgFill }}"></rect><path d="M8 16.5 12 7.5l4 9"></path><path d="M9.3 13.5h5.4"></path></svg>
|
||||
</button>
|
||||
<sc-if value="{{ bgOpen }}" hint-placeholder-val="{{ false }}">
|
||||
<div role="dialog" aria-label="배경 색" onKeyDown="{{ onPopKey }}" style="position: absolute; top: 48px; left: 0; z-index: 30; width: 186px; box-sizing: border-box; padding: 10px; display: flex; flex-direction: column; gap: 8px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<div style="display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 0 2px">
|
||||
<span style="font-size: 12.5px; font-weight: 600; color: #4A5363">배경 색</span>
|
||||
<span style="font-size: 12px; color: #667085">{{ bgName }}</span>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px">
|
||||
<sc-for list="{{ bgColors }}" as="c" hint-placeholder-count="8">
|
||||
<button type="button" class="sw" onClick="{{ c.pick }}" aria-label="{{ c.name }}" aria-pressed="{{ c.pressed }}" title="{{ c.name }}" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<span style="width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; background: {{ c.hex }}; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14); color: {{ c.checkColor }}">
|
||||
<sc-if value="{{ c.slash }}" hint-placeholder-val="{{ false }}"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#B42318" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="5" y1="19" x2="19" y2="5"></line></svg></sc-if>
|
||||
<sc-if value="{{ c.on }}" hint-placeholder-val="{{ false }}"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if>
|
||||
</span>
|
||||
</button>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
|
||||
<div class="tg-e" style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" class="tb" onClick="{{ toggleBullet }}" aria-pressed="{{ bulletPressed }}" aria-label="글머리 목록" aria-keyshortcuts="Control+Shift+8" title="글머리 목록 (Ctrl+Shift+8)" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="9" y1="6" x2="20" y2="6"></line><line x1="9" y1="12" x2="20" y2="12"></line><line x1="9" y1="18" x2="20" y2="18"></line><circle cx="4.5" cy="6" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="12" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="18" r="1.2" fill="currentColor" stroke="none"></circle></svg>
|
||||
</button>
|
||||
<button type="button" class="tb" onClick="{{ toggleOrdered }}" aria-pressed="{{ orderedPressed }}" aria-label="번호 목록" aria-keyshortcuts="Control+Shift+7" title="번호 목록 (Ctrl+Shift+7)" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="12"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg>
|
||||
</button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
|
||||
<div class="tg-f" style="display: flex; align-items: center; gap: 2px">
|
||||
<div style="position: relative; display: flex">
|
||||
<button type="button" class="tb" onClick="{{ openLink }}" aria-haspopup="dialog" aria-expanded="{{ linkExpanded }}" aria-label="링크" aria-keyshortcuts="Control+K" title="링크 (Ctrl+K)" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</button>
|
||||
<sc-if value="{{ linkOpen }}" hint-placeholder-val="{{ false }}">
|
||||
<div role="dialog" aria-label="링크 넣기" onKeyDown="{{ onPopKey }}" style="position: absolute; top: 48px; right: 0; z-index: 30; width: 300px; box-sizing: border-box; padding: 14px; display: flex; flex-direction: column; gap: 10px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<label for="link-url" style="font-size: 12.5px; font-weight: 600; color: #344054">주소</label>
|
||||
<input id="link-url" type="url" placeholder="https://" style="min-height: 40px; box-sizing: border-box; padding: 0 12px; border: 1px solid #8A94A3; border-radius: 8px; font: inherit; color: #171C26; background: #FFFFFF">
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<label for="link-text" style="font-size: 12.5px; font-weight: 600; color: #344054">표시할 글자</label>
|
||||
<input id="link-text" type="text" placeholder="비우면 주소를 그대로 보여 줍니다" style="min-height: 40px; box-sizing: border-box; padding: 0 12px; border: 1px solid #8A94A3; border-radius: 8px; font: inherit; color: #171C26; background: #FFFFFF">
|
||||
</div>
|
||||
<div style="display: flex; justify-content: flex-end; gap: 6px">
|
||||
<button type="button" onClick="{{ closeMenus }}" style="min-height: 44px; padding: 0 14px; border: 0; border-radius: 8px; background: transparent; color: #344054; font: inherit; font-weight: 500; cursor: pointer">취소</button>
|
||||
<button type="button" onClick="{{ closeMenus }}" style="min-height: 44px; padding: 0 18px; border: 0; border-radius: 8px; background: #0E7C86; color: #FFFFFF; font: inherit; font-weight: 600; cursor: pointer">넣기</button>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
|
||||
<div style="position: relative; display: flex">
|
||||
<button type="button" class="tb" onClick="{{ openMore }}" aria-haspopup="menu" aria-expanded="{{ moreExpanded }}" aria-label="서식 더보기" title="서식 더보기" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none" aria-hidden="true"><circle cx="5" cy="12" r="1.6"></circle><circle cx="12" cy="12" r="1.6"></circle><circle cx="19" cy="12" r="1.6"></circle></svg>
|
||||
</button>
|
||||
<sc-if value="{{ moreOpen }}" hint-placeholder-val="{{ false }}">
|
||||
<div role="menu" aria-label="서식 더보기" onKeyDown="{{ onPopKey }}" style="position: absolute; top: 48px; right: 0; z-index: 30; width: 256px; max-height: min(560px, 70vh); overflow-y: auto; box-sizing: border-box; padding: 6px; display: flex; flex-direction: column; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
|
||||
<div class="mm-a" style="flex-direction: column">
|
||||
<button type="button" role="menuitem" class="mi" disabled="{{ undoDisabled }}" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M9 14 4 9l5-5"></path><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"></path></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">실행 취소</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Z</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px"></span>
|
||||
</button>
|
||||
<button type="button" role="menuitem" class="mi" disabled="{{ true }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="m15 14 5-5-5-5"></path><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"></path></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">다시 실행</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Y</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px"></span>
|
||||
</button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
</div>
|
||||
|
||||
<div class="mm-b" style="flex-direction: column">
|
||||
<button type="button" role="menuitem" aria-haspopup="menu" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><polyline points="4 7 4 4 20 4 20 7"></polyline><line x1="9" y1="20" x2="15" y2="20"></line><line x1="12" y1="4" x2="12" y2="20"></line></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">글꼴</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">{{ fontName }}</span>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 1px; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||
</button>
|
||||
<button type="button" role="menuitem" aria-haspopup="menu" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M3 7V5h10v2"></path><path d="M8 5v14"></path><path d="M6 19h4"></path><path d="M14 12v-1h7v1"></path><path d="M17.5 11v8"></path><path d="M16 19h3"></path></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">글자 크기</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">{{ sizeLabel }}</span>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 1px; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||
</button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column">
|
||||
<button type="button" role="menuitemcheckbox" aria-checked="{{ strikeChecked }}" class="mi" onClick="{{ toggleStrike }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M16 4H9a3 3 0 0 0-2.83 4"></path><path d="M14 12a4 4 0 0 1 0 8H6"></path><line x1="4" y1="12" x2="20" y2="12"></line></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">취소선</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Shift+S</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px; display: inline-flex"><sc-if value="{{ strikeOn }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if></span>
|
||||
</button>
|
||||
<div class="mm-d" style="flex-direction: column">
|
||||
<button type="button" role="menuitem" aria-haspopup="dialog" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M6.5 14.5 12 3.5l5.5 11"></path><path d="M8.5 10.5h7"></path><rect x="4.5" y="18" width="15" height="3" rx="1" fill="{{ colorHex }}" stroke="none"></rect></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">글자 색</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">{{ colorName }}</span>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 1px; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||
</button>
|
||||
<button type="button" role="menuitem" aria-haspopup="dialog" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><rect x="3.5" y="3.5" width="17" height="17" rx="3" fill="{{ bgFill }}"></rect><path d="M8 16.5 12 7.5l4 9"></path><path d="M9.3 13.5h5.4"></path></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">배경 색</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">{{ bgName }}</span>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 1px; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||
</button>
|
||||
</div>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column">
|
||||
<div class="mm-e" style="flex-direction: column">
|
||||
<button type="button" role="menuitemcheckbox" aria-checked="{{ bulletChecked }}" class="mi" onClick="{{ toggleBulletMenu }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="9" y1="6" x2="20" y2="6"></line><line x1="9" y1="12" x2="20" y2="12"></line><line x1="9" y1="18" x2="20" y2="18"></line><circle cx="4.5" cy="6" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="12" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="18" r="1.2" fill="currentColor" stroke="none"></circle></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">글머리 목록</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Shift+8</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px; display: inline-flex"><sc-if value="{{ bulletOn }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if></span>
|
||||
</button>
|
||||
<button type="button" role="menuitemcheckbox" aria-checked="{{ orderedChecked }}" class="mi" onClick="{{ toggleOrderedMenu }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="12"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">번호 목록</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Shift+7</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px; display: inline-flex"><sc-if value="{{ orderedOn }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if></span>
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" role="menuitemradio" aria-checked="{{ alignLeftChecked }}" class="mi" onClick="{{ setAlignLeft }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="17" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="17" y1="18" x2="3" y2="18"></line></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">왼쪽 정렬</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Shift+L</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px; display: inline-flex"><sc-if value="{{ alignLeftOn }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if></span>
|
||||
</button>
|
||||
<button type="button" role="menuitemradio" aria-checked="{{ alignCenterChecked }}" class="mi" onClick="{{ setAlignCenter }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="18" y1="10" x2="6" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="18" y1="18" x2="6" y2="18"></line></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">가운데 정렬</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Shift+E</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px; display: inline-flex"><sc-if value="{{ alignCenterOn }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if></span>
|
||||
</button>
|
||||
<button type="button" role="menuitemradio" aria-checked="{{ alignRightChecked }}" class="mi" onClick="{{ setAlignRight }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="21" y1="10" x2="7" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="21" y1="18" x2="7" y2="18"></line></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">오른쪽 정렬</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Shift+R</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px; display: inline-flex"><sc-if value="{{ alignRightOn }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if></span>
|
||||
</button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column">
|
||||
<button type="button" role="menuitem" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><polyline points="7 8 3 12 7 16"></polyline><line x1="21" y1="12" x2="11" y2="12"></line><line x1="21" y1="6" x2="11" y2="6"></line><line x1="21" y1="18" x2="11" y2="18"></line></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">내어쓰기</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+[</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px"></span>
|
||||
</button>
|
||||
<button type="button" role="menuitem" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><polyline points="3 8 7 12 3 16"></polyline><line x1="21" y1="12" x2="11" y2="12"></line><line x1="21" y1="6" x2="11" y2="6"></line><line x1="21" y1="18" x2="11" y2="18"></line></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">들여쓰기</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+]</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px"></span>
|
||||
</button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column">
|
||||
<div class="mm-f" style="flex-direction: column">
|
||||
<button type="button" role="menuitem" aria-haspopup="dialog" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">링크 넣기</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+K</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px"></span>
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" role="menuitemcheckbox" aria-checked="{{ quoteChecked }}" class="mi" onClick="{{ toggleQuote }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M17 6H3"></path><path d="M21 12H8"></path><path d="M21 18H8"></path><path d="M3 12v6"></path></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">인용</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+Shift+B</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px; display: inline-flex"><sc-if value="{{ quoteOn }}" hint-placeholder-val="{{ false }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></sc-if></span>
|
||||
</button>
|
||||
<button type="button" role="menuitem" aria-haspopup="dialog" class="mi" onClick="{{ openTable }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="3" y1="15" x2="21" y2="15"></line><line x1="9" y1="3" x2="9" y2="21"></line><line x1="15" y1="3" x2="15" y2="21"></line></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">표 넣기</span>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 1px; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||
</button>
|
||||
<button type="button" role="menuitem" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="3" y1="12" x2="21" y2="12"></line><polyline points="8 8 12 4 16 8"></polyline><polyline points="16 16 12 20 8 16"></polyline></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">가로줄</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px"></span>
|
||||
</button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
</div>
|
||||
|
||||
<button type="button" role="menuitem" class="mi" onClick="{{ closeMenus }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; font: inherit; text-align: left; cursor: pointer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M4 7V4h16v3"></path><path d="M5 20h6"></path><path d="M13 4 8 20"></path><path d="m15 15 5 5"></path><path d="m20 15-5 5"></path></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0">서식 지우기</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085">Ctrl+\</span>
|
||||
<span style="flex: 0 0 auto; width: 16px; height: 16px"></span>
|
||||
</button>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ tableOpen }}" hint-placeholder-val="{{ false }}">
|
||||
<div role="dialog" aria-label="표 넣기" onKeyDown="{{ onPopKey }}" style="position: absolute; top: 48px; right: 0; z-index: 30; box-sizing: border-box; padding: 12px; display: flex; flex-direction: column; gap: 8px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<span style="font-size: 12.5px; font-weight: 600; color: #4A5363">표 넣기</span>
|
||||
<div style="display: grid; grid-template-columns: repeat(8, 22px); gap: 3px">
|
||||
<sc-for list="{{ cells }}" as="cell" hint-placeholder-count="48">
|
||||
<button type="button" onClick="{{ cell.pick }}" onMouseEnter="{{ cell.hover }}" onFocus="{{ cell.hover }}" aria-label="{{ cell.label }}" style="width: 22px; height: 22px; box-sizing: border-box; padding: 0; border: 1px solid {{ cell.border }}; border-radius: 3px; background: {{ cell.bg }}; cursor: pointer"></button>
|
||||
</sc-for>
|
||||
</div>
|
||||
<span aria-live="polite" style="font-size: 12.5px; color: #344054; font-variant-numeric: tabular-nums">{{ tableSize }}</span>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="cf" style="position: relative; flex: 1 1 0px; min-height: 300px; display: flex; flex-direction: column; overflow-y: auto; border-bottom: 1px solid #EEF0F3">
|
||||
<sc-if value="{{ dragging }}" hint-placeholder-val="{{ false }}">
|
||||
<div aria-hidden="true" style="position: absolute; inset: 8px; z-index: 1; pointer-events: none; display: flex; align-items: center; justify-content: center; gap: 8px; border: 2px dashed #0E7C86; border-radius: 8px; background: rgba(243, 248, 248, 0.94); color: #0A5F67; font-weight: 600">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>
|
||||
<span>놓으면 첨부 파일로 올립니다</span>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ isReply }}" hint-placeholder-val="{{ true }}">
|
||||
<div id="compose-body" class="ce cf-in" onPaste="{{ onBodyPaste }}" contenteditable="true" tabindex="0" role="textbox" aria-multiline="true" aria-label="본문" style="flex: 1 1 auto; max-width: 744px; box-sizing: border-box; padding: 16px 32px 28px; font-family: {{ bodyFont }}; font-size: 14px; line-height: 1.75; color: #1F2733; outline: none">
|
||||
<p>도윤님, 확인했습니다.</p>
|
||||
<p>체크리스트 기준으로 <strong>금요일 저녁 전환</strong>을 진행해 주세요.</p>
|
||||
<ul>
|
||||
<li>전환 하루 전에 DNS TTL을 300초로 낮추기</li>
|
||||
<li>기존 서버는 2주 동안 함께 운영</li>
|
||||
</ul>
|
||||
<p><br></p>
|
||||
<p>김아라</p>
|
||||
<blockquote style="margin: 24px 0 0; padding: 2px 0 2px 14px; border-left: 2px solid #D0D5DD; color: #4A5363">
|
||||
<div contenteditable="false" style="margin: 0 0 12px; font-size: 12.5px; line-height: 1.6">
|
||||
<p style="font-weight: 600">원본 메일</p>
|
||||
<table style="border-collapse: collapse; font-size: 12.5px; line-height: 1.6">
|
||||
<tbody>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">보낸 사람</th><td style="padding: 0">이도윤 <doyun.lee@arasystem.it.kr></td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">날짜</th><td style="padding: 0">2026. 10. 26. (월) 오전 10:42</td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">제목</th><td style="padding: 0">Re: 메일 서버 이전 일정 공유</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>김아라님, 안녕하세요.</p>
|
||||
<p><br></p>
|
||||
<p>말씀하신 대로 이번 주 금요일(10/30) 저녁 9시에 MX 레코드를 새 메일 서버로 전환하겠습니다.</p>
|
||||
<p>전환 하루 전에 DNS TTL을 300초로 낮춰 두고, 기존 서버는 2주 동안 함께 운영합니다.</p>
|
||||
<p><br></p>
|
||||
<p>전환 체크리스트를 첨부했으니 확인 부탁드립니다.</p>
|
||||
<p><br></p>
|
||||
<p>이도윤 드림</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ isForward }}" hint-placeholder-val="{{ false }}">
|
||||
<div id="compose-body" class="ce cf-in" onPaste="{{ onBodyPaste }}" contenteditable="true" tabindex="0" role="textbox" aria-multiline="true" aria-label="본문" style="flex: 1 1 auto; max-width: 744px; box-sizing: border-box; padding: 16px 32px 28px; font-family: {{ bodyFont }}; font-size: 14px; line-height: 1.75; color: #1F2733; outline: none">
|
||||
<p><br></p>
|
||||
<blockquote style="margin: 24px 0 0; padding: 2px 0 2px 14px; border-left: 2px solid #D0D5DD; color: #4A5363">
|
||||
<div contenteditable="false" style="margin: 0 0 12px; font-size: 12.5px; line-height: 1.6">
|
||||
<p style="font-weight: 600">원본 메일</p>
|
||||
<table style="border-collapse: collapse; font-size: 12.5px; line-height: 1.6">
|
||||
<tbody>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">보낸 사람</th><td style="padding: 0">이도윤 <doyun.lee@arasystem.it.kr></td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">날짜</th><td style="padding: 0">2026. 10. 26. (월) 오전 10:42</td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">받는 사람</th><td style="padding: 0">김아라 <ara.kim@arasystem.it.kr></td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">참조</th><td style="padding: 0">인프라팀 <infra@arasystem.it.kr></td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">제목</th><td style="padding: 0">Re: 메일 서버 이전 일정 공유</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>김아라님, 안녕하세요.</p>
|
||||
<p><br></p>
|
||||
<p>말씀하신 대로 이번 주 금요일(10/30) 저녁 9시에 MX 레코드를 새 메일 서버로 전환하겠습니다.</p>
|
||||
<p>전환 하루 전에 DNS TTL을 300초로 낮춰 두고, 기존 서버는 2주 동안 함께 운영합니다.</p>
|
||||
<p><br></p>
|
||||
<p>전환 체크리스트를 첨부했으니 확인 부탁드립니다.</p>
|
||||
<p><br></p>
|
||||
<p>이도윤 드림</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ isNew }}" hint-placeholder-val="{{ false }}">
|
||||
<div id="compose-body" class="ce cf-in" onPaste="{{ onBodyPaste }}" contenteditable="true" tabindex="0" role="textbox" aria-multiline="true" aria-label="본문" data-placeholder="내용을 입력하세요" style="flex: 1 1 auto; max-width: 744px; box-sizing: border-box; padding: 16px 32px 28px; font-family: {{ bodyFont }}; font-size: 14px; line-height: 1.75; color: #1F2733; outline: none"></div>
|
||||
</sc-if>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 8px; padding: 10px 32px 14px">
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px">
|
||||
<button type="button" style="display: inline-flex; align-items: center; gap: 6px; min-height: 44px; margin-left: -6px; padding: 0 10px 0 6px; border: 0; border-radius: 8px; background: transparent; color: #344054; font: inherit; font-weight: 500; cursor: pointer">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>
|
||||
<span>파일 첨부</span>
|
||||
</button>
|
||||
<span style="font-size: 12px; color: #667085">파일당 최대 20MB · 문서, 이미지, 압축 파일</span>
|
||||
<span style="font-size: 12px; color: #667085">파일당 최대 20MB · 합계 25MB · 최대 20개 · 문서, 이미지, 압축 파일</span>
|
||||
</div>
|
||||
<sc-if value="{{ hasFiles }}" hint-placeholder-val="{{ true }}">
|
||||
<ul style="list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap: 6px">
|
||||
@@ -208,33 +629,153 @@ a{color:#0E7C86}a:hover{color:#0A5F67}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<sc-if value="{{ notice }}" hint-placeholder-val="{{ false }}">
|
||||
<div role="status" style="position: fixed; right: 24px; bottom: 24px; z-index: 40; display: flex; align-items: center; gap: 10px; max-width: calc(100vw - 48px); box-sizing: border-box; padding: 6px 6px 6px 14px; border-radius: 10px; background: #0B3640; color: #FFFFFF; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.22)">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#9FE0B5" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="20 6 9 17 4 12"></polyline></svg>
|
||||
<span style="flex: 1 1 auto; font-weight: 500">이미지는 본문 대신 첨부 파일로 올렸습니다.</span>
|
||||
<button type="button" class="on-dark" onClick="{{ hideNotice }}" aria-label="알림 닫기" style="flex: 0 0 auto; width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 6px; background: transparent; color: #A3C2C6; cursor: pointer">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
||||
</button>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props='{"mode":{"editor":"enum","options":["reply","new"],"default":"reply"},"$preview":{"width":1440,"height":900}}'>
|
||||
<script type="text/x-dc" data-dc-script data-props='{"mode":{"editor":"enum","options":["reply","forward","new"],"default":"reply"},"bodyFont":{"editor":"enum","options":["malgun","pretendard"],"default":"malgun"},"$preview":{"width":1440,"height":900}}'>
|
||||
class Component extends DCLogic {
|
||||
state = { mode: null };
|
||||
|
||||
initial(mode) {
|
||||
// 툴바 서식 상태는 모드마다 처음부터 시작한다
|
||||
const ui = {
|
||||
open: null, bold: false, italic: false, underline: false, strike: false,
|
||||
bullet: false, ordered: false, quote: false, align: 'left',
|
||||
font: 'base', size: 14, color: 'auto', bg: 'none', rows: 3, cols: 4,
|
||||
dragging: false, notice: false,
|
||||
};
|
||||
if (mode === 'new') {
|
||||
return { mode: 'new', chips: [], toInput: '', showCc: false, subject: '', body: '', files: [] };
|
||||
return Object.assign({}, ui, { mode: 'new', chips: [], toInput: '', showCc: false, subject: '', files: [] });
|
||||
}
|
||||
return {
|
||||
if (mode === 'forward') {
|
||||
return Object.assign({}, ui, {
|
||||
mode: 'forward', chips: [], toInput: '', showCc: false,
|
||||
subject: 'Fwd: Re: 메일 서버 이전 일정 공유',
|
||||
files: [{ name: '메일서버_전환_체크리스트.xlsx', size: '48 KB' }],
|
||||
});
|
||||
}
|
||||
return Object.assign({}, ui, {
|
||||
mode: 'reply',
|
||||
chips: [{ label: '이도윤 <doyun.lee@arasystem.it.kr>', invalid: false }],
|
||||
toInput: '',
|
||||
showCc: false,
|
||||
subject: 'Re: 메일 서버 이전 일정 공유',
|
||||
body: '도윤님, 확인했습니다.\n체크리스트 기준으로 금요일 저녁 전환을 진행해 주세요.\n\n김아라\n\n──────────\n2026. 10. 26. (월) 오전 10:42, 이도윤 <doyun.lee@arasystem.it.kr> 작성:\n> 김아라님, 안녕하세요.\n> 말씀하신 대로 이번 주 금요일(10/30) 저녁 9시에 MX 레코드를 새 메일 서버로 전환하겠습니다.',
|
||||
files: [{ name: '메일서버_전환_체크리스트_v2.xlsx', size: '52 KB' }],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
renderVals() {
|
||||
const mode = this.props.mode ?? 'reply';
|
||||
// 모드(답장/새 메일)가 바뀌면 그 모드의 초기값에서 다시 시작한다
|
||||
// 모드(답장/전달/새 메일)가 바뀌면 그 모드의 초기값에서 다시 시작한다
|
||||
const data = this.state.mode === mode ? this.state : this.initial(mode);
|
||||
const update = (patch) => this.setState({ ...data, ...patch });
|
||||
const update = (patch) => this.setState(Object.assign({}, data, patch));
|
||||
const EMAIL = /^[^@\s<>]+@[^@\s<>]+\.[^@\s<>]+$/;
|
||||
const flag = (value) => (value ? 'true' : 'false');
|
||||
|
||||
// 본문 기본 글꼴 — 맑은 고딕 스택으로 확정 (편집기 안 모양 = 받는 사람이 보는 모양)
|
||||
const BODY_FONTS = {
|
||||
malgun: "'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif",
|
||||
pretendard: "Pretendard, -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', system-ui, sans-serif",
|
||||
};
|
||||
const bodyFontId = this.props.bodyFont === 'pretendard' ? 'pretendard' : 'malgun';
|
||||
const bodyFont = BODY_FONTS[bodyFontId];
|
||||
const FONTS_KO = [
|
||||
// 첫 항목이 본문 기본 글꼴 — 고르면 글꼴 지정을 지운다
|
||||
{ id: 'base', label: bodyFontId === 'pretendard' ? 'Pretendard' : '맑은 고딕', family: bodyFont, isBase: true },
|
||||
{ id: 'gulim', label: '굴림', family: "Gulim, '굴림', sans-serif" },
|
||||
{ id: 'dotum', label: '돋움', family: "Dotum, '돋움', sans-serif" },
|
||||
{ id: 'batang', label: '바탕', family: "Batang, '바탕', serif" },
|
||||
];
|
||||
const FONTS_EN = [
|
||||
{ id: 'arial', label: 'Arial', family: 'Arial, sans-serif' },
|
||||
{ id: 'verdana', label: 'Verdana', family: 'Verdana, sans-serif' },
|
||||
{ id: 'georgia', label: 'Georgia', family: 'Georgia, serif' },
|
||||
{ id: 'times', label: 'Times New Roman', family: "'Times New Roman', serif" },
|
||||
{ id: 'courier', label: 'Courier New', family: "'Courier New', monospace" },
|
||||
];
|
||||
const SIZES = [12, 13, 14, 16, 18, 20, 24, 32];
|
||||
// 글자 색은 모두 흰 바탕 4.5:1 이상
|
||||
const TEXT_COLORS = [
|
||||
{ id: 'auto', name: '기본', hex: '#1F2733', dark: true },
|
||||
{ id: 'gray', name: '회색', hex: '#667085', dark: true },
|
||||
{ id: 'red', name: '빨강', hex: '#B42318', dark: true },
|
||||
{ id: 'orange', name: '주황', hex: '#B54708', dark: true },
|
||||
{ id: 'green', name: '초록', hex: '#067647', dark: true },
|
||||
{ id: 'teal', name: '청록', hex: '#0E7C86', dark: true },
|
||||
{ id: 'blue', name: '파랑', hex: '#175CD3', dark: true },
|
||||
{ id: 'purple', name: '보라', hex: '#6941C6', dark: true },
|
||||
];
|
||||
// 배경 색은 본문 글자(#1F2733)가 10:1 이상 남는 옅은 색만
|
||||
const BG_COLORS = [
|
||||
{ id: 'none', name: '없음', hex: '#FFFFFF', none: true },
|
||||
{ id: 'yellow', name: '노랑', hex: '#FFF1A8' },
|
||||
{ id: 'orange', name: '주황', hex: '#FDE4CC' },
|
||||
{ id: 'pink', name: '분홍', hex: '#FBDCE3' },
|
||||
{ id: 'green', name: '초록', hex: '#D9F2DF' },
|
||||
{ id: 'sky', name: '하늘', hex: '#D6E8FB' },
|
||||
{ id: 'purple', name: '보라', hex: '#E9E0FA' },
|
||||
{ id: 'gray', name: '회색', hex: '#E9EBEF' },
|
||||
];
|
||||
|
||||
const open = data.open;
|
||||
// 메뉴·팝오버는 한 번에 하나만 열린다
|
||||
const opener = (name) => () => update({ open: open === name ? null : name });
|
||||
const close = () => update({ open: null });
|
||||
|
||||
const fontItem = (f) => ({
|
||||
label: f.label,
|
||||
family: f.family,
|
||||
isBase: Boolean(f.isBase),
|
||||
on: f.id === data.font,
|
||||
checked: flag(f.id === data.font),
|
||||
pick: () => update({ font: f.id, open: null }),
|
||||
});
|
||||
const currentFont = FONTS_KO.concat(FONTS_EN).find((f) => f.id === data.font) ?? FONTS_KO[0];
|
||||
const sizes = SIZES.map((px) => ({
|
||||
label: String(px),
|
||||
px: px + 'px',
|
||||
isBase: px === 14,
|
||||
on: px === data.size,
|
||||
checked: flag(px === data.size),
|
||||
pick: () => update({ size: px, open: null }),
|
||||
}));
|
||||
const swatch = (c, current, key) => ({
|
||||
name: c.name,
|
||||
hex: c.hex,
|
||||
on: c.id === current,
|
||||
pressed: flag(c.id === current),
|
||||
slash: Boolean(c.none) && c.id !== current,
|
||||
checkColor: c.dark ? '#FFFFFF' : '#171C26',
|
||||
pick: () => update({ [key]: c.id, open: null }),
|
||||
});
|
||||
const textColor = TEXT_COLORS.find((c) => c.id === data.color) ?? TEXT_COLORS[0];
|
||||
const bgColor = BG_COLORS.find((c) => c.id === data.bg) ?? BG_COLORS[0];
|
||||
|
||||
// 표 넣기 — 8열 × 6행 격자, 올린 칸까지 고른다
|
||||
const cells = [];
|
||||
for (let r = 1; r <= 6; r += 1) {
|
||||
for (let c = 1; c <= 8; c += 1) {
|
||||
const on = r <= data.rows && c <= data.cols;
|
||||
cells.push({
|
||||
label: r + '행 ' + c + '열 표 넣기',
|
||||
bg: on ? '#E3F2F3' : '#FFFFFF',
|
||||
border: on ? '#0E7C86' : '#D0D5DD',
|
||||
hover: () => {
|
||||
if (data.rows !== r || data.cols !== c) update({ rows: r, cols: c });
|
||||
},
|
||||
pick: close,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const chips = data.chips.map((c, i) => ({
|
||||
label: c.label,
|
||||
@@ -252,17 +793,141 @@ class Component extends DCLogic {
|
||||
remove: () => update({ files: data.files.filter((_, j) => j !== i) }),
|
||||
}));
|
||||
|
||||
const alignTo = (id) => () => update({ align: id, open: null });
|
||||
|
||||
// 본문에는 이미지를 넣지 않는다 — 붙여 넣거나 끌어다 놓은 파일은 첨부로 올리고, 이미지였으면 알린다
|
||||
const formatSize = (bytes) => (bytes >= 1048576 ? (bytes / 1048576).toFixed(1) + ' MB' : Math.max(1, Math.round(bytes / 1024)) + ' KB');
|
||||
const hasFiles = (e) => Array.prototype.indexOf.call((e.dataTransfer && e.dataTransfer.types) || [], 'Files') !== -1;
|
||||
const attachFiles = (list) => {
|
||||
if (list.length === 0) return;
|
||||
const hasImage = list.some((f) => /^image\//.test(f.type));
|
||||
update({
|
||||
files: data.files.concat(list.map((f) => ({ name: f.name || 'image.png', size: formatSize(f.size || 0) }))),
|
||||
dragging: false,
|
||||
notice: hasImage,
|
||||
});
|
||||
if (hasImage) {
|
||||
clearTimeout(this.noticeTimer);
|
||||
// 성공 알림과 같은 5초 (toast.store TOAST_DURATION_MS.success)
|
||||
this.noticeTimer = setTimeout(() => this.setState({ notice: false }), 5000);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
title: mode === 'new' ? '새 메일' : '답장',
|
||||
title: mode === 'new' ? '새 메일' : mode === 'forward' ? '전달' : '답장',
|
||||
chips: chips,
|
||||
hasInvalid: data.chips.some((c) => c.invalid),
|
||||
toInput: data.toInput,
|
||||
showCc: data.showCc,
|
||||
ccExpanded: data.showCc ? 'true' : 'false',
|
||||
ccExpanded: flag(data.showCc),
|
||||
subject: data.subject,
|
||||
body: data.body,
|
||||
files: files,
|
||||
hasFiles: files.length > 0,
|
||||
isReply: mode === 'reply',
|
||||
isForward: mode === 'forward',
|
||||
isNew: mode === 'new',
|
||||
bodyFont: bodyFont,
|
||||
undoDisabled: mode !== 'reply',
|
||||
|
||||
fontName: currentFont.label,
|
||||
fontOpen: open === 'font',
|
||||
fontExpanded: flag(open === 'font'),
|
||||
openFont: opener('font'),
|
||||
fontsKo: FONTS_KO.map(fontItem),
|
||||
fontsEn: FONTS_EN.map(fontItem),
|
||||
sizeLabel: String(data.size),
|
||||
sizeOpen: open === 'size',
|
||||
sizeExpanded: flag(open === 'size'),
|
||||
openSize: opener('size'),
|
||||
sizes: sizes,
|
||||
|
||||
boldPressed: flag(data.bold),
|
||||
toggleBold: () => update({ bold: !data.bold }),
|
||||
italicPressed: flag(data.italic),
|
||||
toggleItalic: () => update({ italic: !data.italic }),
|
||||
underlinePressed: flag(data.underline),
|
||||
toggleUnderline: () => update({ underline: !data.underline }),
|
||||
|
||||
colorHex: textColor.hex,
|
||||
colorName: textColor.name,
|
||||
colorOpen: open === 'color',
|
||||
colorExpanded: flag(open === 'color'),
|
||||
openColor: opener('color'),
|
||||
textColors: TEXT_COLORS.map((c) => swatch(c, data.color, 'color')),
|
||||
bgFill: bgColor.none ? 'none' : bgColor.hex,
|
||||
bgName: bgColor.name,
|
||||
bgOpen: open === 'bg',
|
||||
bgExpanded: flag(open === 'bg'),
|
||||
openBg: opener('bg'),
|
||||
bgColors: BG_COLORS.map((c) => swatch(c, data.bg, 'bg')),
|
||||
|
||||
bulletPressed: flag(data.bullet),
|
||||
toggleBullet: () => update({ bullet: !data.bullet, ordered: false }),
|
||||
orderedPressed: flag(data.ordered),
|
||||
toggleOrdered: () => update({ ordered: !data.ordered, bullet: false }),
|
||||
bulletOn: data.bullet,
|
||||
bulletChecked: flag(data.bullet),
|
||||
toggleBulletMenu: () => update({ bullet: !data.bullet, ordered: false, open: null }),
|
||||
orderedOn: data.ordered,
|
||||
orderedChecked: flag(data.ordered),
|
||||
toggleOrderedMenu: () => update({ ordered: !data.ordered, bullet: false, open: null }),
|
||||
|
||||
linkOpen: open === 'link',
|
||||
linkExpanded: flag(open === 'link'),
|
||||
openLink: opener('link'),
|
||||
|
||||
moreOpen: open === 'more',
|
||||
moreExpanded: flag(open === 'more' || open === 'table'),
|
||||
openMore: () => update({ open: open === 'more' || open === 'table' ? null : 'more' }),
|
||||
strikeOn: data.strike,
|
||||
strikeChecked: flag(data.strike),
|
||||
toggleStrike: () => update({ strike: !data.strike, open: null }),
|
||||
quoteOn: data.quote,
|
||||
quoteChecked: flag(data.quote),
|
||||
toggleQuote: () => update({ quote: !data.quote, open: null }),
|
||||
alignLeftOn: data.align === 'left',
|
||||
alignLeftChecked: flag(data.align === 'left'),
|
||||
setAlignLeft: alignTo('left'),
|
||||
alignCenterOn: data.align === 'center',
|
||||
alignCenterChecked: flag(data.align === 'center'),
|
||||
setAlignCenter: alignTo('center'),
|
||||
alignRightOn: data.align === 'right',
|
||||
alignRightChecked: flag(data.align === 'right'),
|
||||
setAlignRight: alignTo('right'),
|
||||
tableOpen: open === 'table',
|
||||
openTable: () => update({ open: 'table' }),
|
||||
cells: cells,
|
||||
tableSize: data.rows + '행 × ' + data.cols + '열',
|
||||
|
||||
closeMenus: close,
|
||||
onPopKey: (e) => {
|
||||
if (e.key === 'Escape') close();
|
||||
},
|
||||
|
||||
dragging: data.dragging,
|
||||
notice: data.notice,
|
||||
hideNotice: () => update({ notice: false }),
|
||||
onFormDragOver: (e) => {
|
||||
if (!hasFiles(e)) return;
|
||||
e.preventDefault();
|
||||
if (!data.dragging) update({ dragging: true });
|
||||
},
|
||||
onFormDragLeave: (e) => {
|
||||
if (e.currentTarget.contains(e.relatedTarget)) return;
|
||||
if (data.dragging) update({ dragging: false });
|
||||
},
|
||||
onFormDrop: (e) => {
|
||||
if (!hasFiles(e)) return;
|
||||
e.preventDefault();
|
||||
attachFiles(Array.from(e.dataTransfer.files));
|
||||
},
|
||||
onBodyPaste: (e) => {
|
||||
const images = Array.from((e.clipboardData && e.clipboardData.files) || []).filter((f) => /^image\//.test(f.type));
|
||||
if (images.length === 0) return;
|
||||
e.preventDefault();
|
||||
attachFiles(images);
|
||||
},
|
||||
|
||||
onToInput: (e) => update({ toInput: e.target.value }),
|
||||
onToKey: (e) => {
|
||||
if (e.key !== 'Enter' && e.key !== ',') return;
|
||||
@@ -270,11 +935,10 @@ class Component extends DCLogic {
|
||||
const value = data.toInput.trim();
|
||||
if (!value) return;
|
||||
const address = value.includes('<') ? value.slice(value.indexOf('<') + 1, value.indexOf('>')) : value;
|
||||
update({ chips: [...data.chips, { label: value, invalid: !EMAIL.test(address) }], toInput: '' });
|
||||
update({ chips: data.chips.concat([{ label: value, invalid: !EMAIL.test(address) }]), toInput: '' });
|
||||
},
|
||||
toggleCc: () => update({ showCc: !data.showCc }),
|
||||
onSubject: (e) => update({ subject: e.target.value }),
|
||||
onBody: (e) => update({ body: e.target.value }),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,652 @@
|
||||
<!doctype html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>메일 쓰기 · 편집기 상태</title>
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<style>
|
||||
@font-face{font-family:'Pretendard';src:url('/_blob/16067b9aa5137abf808e3dbef30c42e0') format('woff2-variations'),url('/_blob/16067b9aa5137abf808e3dbef30c42e0') format('woff2');font-weight:45 920;font-style:normal;font-display:swap}
|
||||
body{margin:0}
|
||||
a{color:#0E7C86}a:hover{color:#0A5F67}
|
||||
:focus-visible{outline:2px solid #0E7C86;outline-offset:2px}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="width: 1440px; min-height: 3576px; box-sizing: border-box; padding: 48px; display: flex; flex-direction: column; gap: 28px; background: #F6F7F9; color: #171C26; font-family: Pretendard, -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', system-ui, sans-serif; font-size: 13px; line-height: 1.5">
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 6px; max-width: 900px">
|
||||
<h1 style="margin: 0; font-size: 24px; font-weight: 700; letter-spacing: -0.02em">메일 쓰기 · 편집기 상태</h1>
|
||||
<p style="margin: 0; font-size: 13.5px; color: #4A5363">본문이 서식 편집기로 바뀝니다. 글자를 쓰는 칸의 포커스는 한 가지 모양으로 보이고, 툴바 버튼은 메일 툴바 버튼과 같은 44px 높이를 씁니다. 본문 글꼴은 맑은 고딕입니다.</p>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 20px">
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; align-items: start">
|
||||
|
||||
<section style="grid-column: span 2; min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">글자 입력칸 포커스 — 한 가지 규칙</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">받는 사람 · 참조 · 숨은참조 · 제목 · 본문 편집기. 커서가 있는 칸의 아래 선이 2px 브랜드색이 됩니다.</p>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 16px; align-items: start">
|
||||
|
||||
<figure style="margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 8px">
|
||||
<div style="display: flex; flex-direction: column; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF; overflow: hidden">
|
||||
<div style="display: flex; align-items: center; gap: 12px; min-height: 52px; box-sizing: border-box; padding: 4px 10px 4px 32px; border-bottom: 1px solid #0E7C86; box-shadow: inset 0 -1px 0 #0E7C86">
|
||||
<span style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">받는 사람</span>
|
||||
<span style="flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px">
|
||||
<span style="display: inline-flex; align-items: center; gap: 2px; min-width: 0; min-height: 28px; box-sizing: border-box; padding: 0 4px 0 8px; border-radius: 4px; background: #F2F4F7; color: #171C26; font-size: 13px">
|
||||
<span style="min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap">이도윤 <doyun.lee@arasystem.it.kr></span>
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 5px"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
||||
</span>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 18px; background: #171C26"></span>
|
||||
</span>
|
||||
<span style="flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 44px; padding: 0 10px; color: #0E7C86; font-size: 12.5px; font-weight: 600">참조 · 숨은참조</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 12px; min-height: 44px; box-sizing: border-box; padding: 4px 10px 4px 32px">
|
||||
<span style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">제목</span>
|
||||
<span style="font-size: 14px; font-weight: 600">Re: 메일 서버 이전 일정 공유</span>
|
||||
</div>
|
||||
</div>
|
||||
<figcaption style="font-size: 12.5px; color: #344054"><strong style="font-weight: 600">① 받는 사람 · 참조 · 숨은참조</strong> — 칩까지 포함한 행 전체의 아래 선</figcaption>
|
||||
</figure>
|
||||
|
||||
<figure style="margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 8px">
|
||||
<div style="display: flex; flex-direction: column; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF; overflow: hidden">
|
||||
<div style="display: flex; align-items: center; gap: 12px; min-height: 52px; box-sizing: border-box; padding: 4px 10px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<span style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">받는 사람</span>
|
||||
<span style="flex: 1 1 auto; min-width: 0; display: flex; align-items: center">
|
||||
<span style="display: inline-flex; align-items: center; gap: 2px; min-width: 0; min-height: 28px; box-sizing: border-box; padding: 0 4px 0 8px; border-radius: 4px; background: #F2F4F7; color: #171C26; font-size: 13px">
|
||||
<span style="min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap">이도윤 <doyun.lee@arasystem.it.kr></span>
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 5px"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
||||
</span>
|
||||
</span>
|
||||
<span style="flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 44px; padding: 0 10px; color: #0E7C86; font-size: 12.5px; font-weight: 600">참조 · 숨은참조</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 12px; min-height: 44px; box-sizing: border-box; padding: 4px 10px 4px 32px; border-bottom: 1px solid #0E7C86; box-shadow: inset 0 -1px 0 #0E7C86">
|
||||
<span style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">제목</span>
|
||||
<span style="display: inline-flex; align-items: center; gap: 1px; font-size: 14px; font-weight: 600">Re: 메일 서버 이전 일정 공유<span aria-hidden="true" style="width: 1px; height: 18px; background: #171C26"></span></span>
|
||||
</div>
|
||||
</div>
|
||||
<figcaption style="font-size: 12.5px; color: #344054"><strong style="font-weight: 600">② 제목</strong> — 같은 자리, 같은 두께</figcaption>
|
||||
</figure>
|
||||
|
||||
<figure style="margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 8px">
|
||||
<div style="display: flex; flex-direction: column; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF; overflow: hidden">
|
||||
<div style="display: flex; align-items: center; gap: 2px; min-height: 52px; box-sizing: border-box; padding: 4px 20px; border-bottom: 1px solid #EEF0F3">
|
||||
<button type="button" aria-label="굵게" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<button type="button" aria-label="기울임" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg></button>
|
||||
<button type="button" aria-label="밑줄" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 3v7a6 6 0 0 0 12 0V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="글머리 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="9" y1="6" x2="20" y2="6"></line><line x1="9" y1="12" x2="20" y2="12"></line><line x1="9" y1="18" x2="20" y2="18"></line><circle cx="4.5" cy="6" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="12" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="18" r="1.2" fill="currentColor" stroke="none"></circle></svg></button>
|
||||
<button type="button" aria-label="번호 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="12"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="링크" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="서식 더보기" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none" aria-hidden="true"><circle cx="5" cy="12" r="1.6"></circle><circle cx="12" cy="12" r="1.6"></circle><circle cx="19" cy="12" r="1.6"></circle></svg></button>
|
||||
</div>
|
||||
<div style="min-height: 104px; box-sizing: border-box; padding: 14px 32px 16px; border-bottom: 1px solid #0E7C86; box-shadow: inset 0 -1px 0 #0E7C86; font-family: 'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif; font-size: 14px; line-height: 1.75; color: #1F2733">
|
||||
<p style="margin: 0">도윤님, 확인했습니다.<span aria-hidden="true" style="display: inline-block; width: 1px; height: 17px; margin-left: 1px; vertical-align: -3px; background: #171C26"></span></p>
|
||||
<p style="margin: 0">체크리스트 기준으로 <strong>금요일 저녁 전환</strong>을 진행해 주세요.</p>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 6px; min-height: 44px; box-sizing: border-box; padding: 0 32px 0 26px; color: #344054; font-weight: 500">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="margin-left: 6px"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>
|
||||
<span>파일 첨부</span>
|
||||
</div>
|
||||
</div>
|
||||
<figcaption style="font-size: 12.5px; color: #344054"><strong style="font-weight: 600">③ 본문 편집기</strong> — 편집 영역 아래 선. 툴바 아래 선은 그대로</figcaption>
|
||||
</figure>
|
||||
|
||||
<figure style="margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 8px">
|
||||
<div style="display: flex; flex-direction: column; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF; overflow: hidden">
|
||||
<div style="display: flex; align-items: center; gap: 12px; min-height: 52px; box-sizing: border-box; padding: 4px 10px 4px 32px; border-bottom: 1px solid #EEF0F3">
|
||||
<span style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">받는 사람</span>
|
||||
<span style="flex: 1 1 auto; min-width: 0; display: flex; align-items: center">
|
||||
<span style="display: inline-flex; align-items: center; gap: 2px; min-width: 0; min-height: 28px; box-sizing: border-box; padding: 0 4px 0 8px; border-radius: 4px; background: #F2F4F7; color: #171C26; font-size: 13px">
|
||||
<span style="min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap">이도윤 <doyun.lee@arasystem.it.kr></span>
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 5px"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
||||
</span>
|
||||
</span>
|
||||
<button type="button" aria-expanded="false" style="flex: 0 0 auto; min-height: 44px; padding: 0 10px; border: 0; border-radius: 8px; background: transparent; color: #0E7C86; font: inherit; font-size: 12.5px; font-weight: 600; outline: 2px solid #0E7C86; outline-offset: 2px; cursor: pointer">참조 · 숨은참조</button>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 12px; min-height: 44px; box-sizing: border-box; padding: 4px 10px 4px 32px">
|
||||
<span style="flex: 0 0 64px; font-size: 12.5px; font-weight: 600; color: #4A5363">제목</span>
|
||||
<span style="font-size: 14px; font-weight: 600">Re: 메일 서버 이전 일정 공유</span>
|
||||
</div>
|
||||
</div>
|
||||
<figcaption style="font-size: 12.5px; color: #344054"><strong style="font-weight: 600">④ 행 안의 버튼</strong> — 버튼에만 고리. 행의 선은 회색 그대로</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 6px">
|
||||
<span style="font-size: 12px; font-weight: 600; color: #4A5363">구현 — tokens.css 변수</span>
|
||||
<code style="display: block; padding: 10px 12px; border-radius: 8px; background: #F6F7F9; font-family: Consolas, 'SFMono-Regular', Menlo, monospace; font-size: 12px; line-height: 1.65; color: #344054">.compose-field:has(:is(input, .ProseMirror):focus)<br> border-bottom-color: var(--color-brand)<br> box-shadow: inset 0 calc(var(--border-width) * -1) 0 var(--color-brand)<br>.compose-field :is(input, .ProseMirror):focus-visible → outline: none</code>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">규칙 — 옮길 값</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">버튼 포커스와 같은 색 · 같은 두께, 모양만 다릅니다</p>
|
||||
</div>
|
||||
<dl style="margin: 0; display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 9px 12px; font-size: 12.5px; line-height: 1.55">
|
||||
<dt style="color: #667085">대상</dt>
|
||||
<dd style="margin: 0">받는 사람 · 참조 · 숨은참조 · 제목 · 본문 편집기</dd>
|
||||
<dt style="color: #667085">위치</dt>
|
||||
<dd style="margin: 0">그 칸의 아래 hairline 자리. 본문은 편집 영역 아래(첨부 영역 위)</dd>
|
||||
<dt style="color: #667085">두께 · 색</dt>
|
||||
<dd style="margin: 0">2px #0E7C86 — 1px 선 색을 바꾸고 안쪽 1px 를 더해 높이가 변하지 않는다</dd>
|
||||
<dt style="color: #667085">모서리</dt>
|
||||
<dd style="margin: 0">없음 (곧은 선)</dd>
|
||||
<dt style="color: #667085">범위</dt>
|
||||
<dd style="margin: 0">행 전체 폭 — 원래 hairline 과 같은 길이 (콘텐츠 열, 최대 800px)</dd>
|
||||
<dt style="color: #667085">언제</dt>
|
||||
<dd style="margin: 0">글자 입력 요소에 포커스가 있을 때. 마우스로 눌러도 보인다</dd>
|
||||
<dt style="color: #667085">대비</dt>
|
||||
<dd style="margin: 0">흰 바탕 4.9:1 · 원래 선 #EEF0F3 4.3:1 · 오류 띠 #FEF3F2 4.5:1</dd>
|
||||
<dt style="color: #667085">버튼</dt>
|
||||
<dd style="margin: 0">2px 고리, 바깥 2px (전역 규칙 그대로). 누르는 것은 고리, 쓰는 곳은 선 — 한 번에 하나만 보인다</dd>
|
||||
<dt style="color: #667085">상자 입력</dt>
|
||||
<dd style="margin: 0">테두리가 있는 입력칸(링크 팝오버 · 로그인)은 상자가 있으므로 버튼처럼 고리</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; align-items: start">
|
||||
|
||||
<section style="grid-column: span 2; min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">본문 툴바 — 800px 열</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">버튼 40×44 (폭 40 은 밀도 예외 · 사용자 확정) · 아이콘 16 · 버튼 사이 2 · 묶음 사이 세로선 1×20 · 툴바 높이 52 (위아래 4)</p>
|
||||
</div>
|
||||
<div style="position: relative; width: 800px; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF">
|
||||
<div role="toolbar" aria-label="본문 서식 (예시)" style="display: flex; align-items: center; gap: 2px; min-height: 52px; box-sizing: border-box; padding: 4px 20px; border-bottom: 1px solid #EEF0F3">
|
||||
<div style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" aria-label="실행 취소" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 14 4 9l5-5"></path><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"></path></svg></button>
|
||||
<button type="button" aria-label="다시 실행" disabled="{{ true }}" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; opacity: 0.5"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 14 5-5-5-5"></path><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" aria-haspopup="menu" aria-label="글꼴: 맑은 고딕" style="width: 108px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; padding: 0 8px 0 12px; border: 0; border-radius: 8px; background: transparent; color: #344054; font: inherit; font-weight: 500; cursor: pointer"><span style="flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left">맑은 고딕</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
|
||||
<button type="button" aria-haspopup="menu" aria-label="글자 크기: 14" style="width: 56px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; padding: 0 8px 0 12px; border: 0; border-radius: 8px; background: transparent; color: #344054; font: inherit; font-weight: 500; cursor: pointer"><span style="flex: 1 1 auto; text-align: left">14</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" aria-label="굵게" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<button type="button" aria-label="기울임" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg></button>
|
||||
<button type="button" aria-label="밑줄" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 3v7a6 6 0 0 0 12 0V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" aria-haspopup="dialog" aria-label="글자 색: 기본" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.5 14.5 12 3.5l5.5 11"></path><path d="M8.5 10.5h7"></path><rect x="4.5" y="18" width="15" height="3" rx="1" fill="#1F2733" stroke="none"></rect></svg></button>
|
||||
<button type="button" aria-haspopup="dialog" aria-label="배경 색: 없음" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="3.5" width="17" height="17" rx="3" fill="none"></rect><path d="M8 16.5 12 7.5l4 9"></path><path d="M9.3 13.5h5.4"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" aria-label="글머리 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="9" y1="6" x2="20" y2="6"></line><line x1="9" y1="12" x2="20" y2="12"></line><line x1="9" y1="18" x2="20" y2="18"></line><circle cx="4.5" cy="6" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="12" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="18" r="1.2" fill="currentColor" stroke="none"></circle></svg></button>
|
||||
<button type="button" aria-label="번호 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="12"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 2px">
|
||||
<button type="button" aria-haspopup="dialog" aria-label="링크" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
</div>
|
||||
<button type="button" aria-haspopup="menu" aria-label="서식 더보기" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none" aria-hidden="true"><circle cx="5" cy="12" r="1.6"></circle><circle cx="12" cy="12" r="1.6"></circle><circle cx="19" cy="12" r="1.6"></circle></svg></button>
|
||||
</div>
|
||||
<div aria-hidden="true" style="display: flex; gap: 2px; padding: 6px 20px 8px; font-size: 11.5px; line-height: 1.4; color: #667085">
|
||||
<span style="flex: 0 0 93px">실행 취소</span>
|
||||
<span style="flex: 0 0 177px">글꼴 · 크기</span>
|
||||
<span style="flex: 0 0 135px">굵게 · 기울임 · 밑줄</span>
|
||||
<span style="flex: 0 0 93px">글자 · 배경 색</span>
|
||||
<span style="flex: 0 0 93px">목록</span>
|
||||
<span style="flex: 0 0 51px">링크</span>
|
||||
<span style="flex: 0 0 40px">더보기</span>
|
||||
</div>
|
||||
<span aria-hidden="true" style="position: absolute; left: 32px; top: 0; bottom: 0; width: 1px; background: #F97066"></span>
|
||||
</div>
|
||||
<ul style="margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: #4A5363">
|
||||
<li>붉은 세로선이 콘텐츠 열 32px 선 — 첫 아이콘(실행 취소)이 여기서 시작한다 (툴바 왼쪽 여백 20 + 버튼 안 12).</li>
|
||||
<li>취소선 · 정렬 · 내어쓰기 · 들여쓰기 · 인용 · 표 · 가로줄 · 서식 지우기는 늘 더보기에 있다.</li>
|
||||
<li>이미지 버튼은 두지 않는다 — 본문에 넣은 이미지는 첨부 파일로 올린다 (맨 아래 카드).</li>
|
||||
<li>키보드: 툴바는 Tab 한 번에 들어가 화살표로 옮긴다. 본문에서 Alt+F10 → 툴바, Esc → 본문.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section style="min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">툴바 버튼 상태</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">MailToolButton 과 같은 높이 44 · 모서리 8 · 글자색</p>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px">
|
||||
<div style="display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px 6px; border: 1px solid #EEF0F3; border-radius: 8px; text-align: center">
|
||||
<button type="button" aria-label="굵게" style="width: 40px; height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<span style="margin-top: 2px; font-size: 12.5px; font-weight: 600">기본</span>
|
||||
<span style="font-size: 11.5px; color: #667085">바탕 없음 · 아이콘 #344054</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px 6px; border: 1px solid #EEF0F3; border-radius: 8px; text-align: center">
|
||||
<button type="button" aria-label="굵게" style="width: 40px; height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: #F2F4F7; color: #171C26; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<span style="margin-top: 2px; font-size: 12.5px; font-weight: 600">마우스 올림</span>
|
||||
<span style="font-size: 11.5px; color: #667085">바탕 #F2F4F7 · 아이콘 #171C26</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px 6px; border: 1px solid #EEF0F3; border-radius: 8px; text-align: center">
|
||||
<button type="button" aria-label="굵게" aria-pressed="true" style="width: 40px; height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: #E3F2F3; box-shadow: inset 0 0 0 1px #0E7C86; color: #0A5F67; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<span style="margin-top: 2px; font-size: 12.5px; font-weight: 600">켜짐 (눌림)</span>
|
||||
<span style="font-size: 11.5px; color: #667085">바탕 #E3F2F3 · 안쪽 1px #0E7C86 · 아이콘 #0A5F67</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px 6px; border: 1px solid #EEF0F3; border-radius: 8px; text-align: center">
|
||||
<button type="button" aria-label="다시 실행" disabled="{{ true }}" style="width: 40px; height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; opacity: 0.5"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 14 5-5-5-5"></path><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"></path></svg></button>
|
||||
<span style="margin-top: 2px; font-size: 12.5px; font-weight: 600">비활성</span>
|
||||
<span style="font-size: 11.5px; color: #667085">50% 투명 (MailToolButton 과 같다)</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px 6px; border: 1px solid #EEF0F3; border-radius: 8px; text-align: center">
|
||||
<button type="button" aria-label="굵게" style="width: 40px; height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; outline: 2px solid #0E7C86; outline-offset: 2px; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<span style="margin-top: 2px; font-size: 12.5px; font-weight: 600">포커스</span>
|
||||
<span style="font-size: 11.5px; color: #667085">2px #0E7C86 고리 · 바깥 2px</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px 6px; border: 1px solid #EEF0F3; border-radius: 8px; text-align: center">
|
||||
<button type="button" aria-haspopup="menu" aria-expanded="true" aria-label="글꼴: 맑은 고딕" style="width: 108px; max-width: 100%; height: 44px; display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; padding: 0 8px 0 12px; border: 0; border-radius: 8px; background: #F2F4F7; color: #171C26; font: inherit; font-weight: 500; cursor: pointer"><span style="flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left">맑은 고딕</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
|
||||
<span style="margin-top: 2px; font-size: 12.5px; font-weight: 600">메뉴 열림</span>
|
||||
<span style="font-size: 11.5px; color: #667085">올림과 같은 바탕</span>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">켜짐에 안쪽 1px 선을 두는 까닭 — 옅은 바탕(#E3F2F3)만으로는 흰 바탕과의 대비가 3:1 에 못 미친다. 선은 4.3:1.</p>
|
||||
<div style="display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; border-radius: 8px; background: #F6F7F9">
|
||||
<span style="font-size: 12.5px; font-weight: 600; color: #344054">밀도 예외 — 사용자 확정 (2026-10-27)</span>
|
||||
<span style="font-size: 12px; color: #4A5363">클릭 영역 44px 기준의 의도된 예외: 툴바 버튼 폭 40 (높이 44) · 메뉴 항목 높이 40 · 색 견본 칸 40×40 · 표 고르기 칸 22 (간격 3, 키보드는 화살표)</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; align-items: start">
|
||||
|
||||
<section style="grid-column: span 2; min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">좁은 폭 — 넘치는 묶음은 더보기로</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">툴바는 늘 한 줄입니다. 정해진 순서로 묶음째 더보기에 들어가고, 더보기 단추에는 숫자를 달지 않습니다.</p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 20px; align-items: flex-start">
|
||||
<div style="flex: 0 0 600px; min-width: 0; display: flex; flex-direction: column; gap: 14px">
|
||||
<figure style="margin: 0; display: flex; flex-direction: column; gap: 6px">
|
||||
<figcaption style="font-size: 12.5px; font-weight: 600; color: #344054">쓰기 칸 600px</figcaption>
|
||||
<div style="width: 600px; box-sizing: border-box; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF">
|
||||
<div style="display: flex; align-items: center; gap: 2px; min-height: 52px; box-sizing: border-box; padding: 4px 20px">
|
||||
<button type="button" aria-label="굵게" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<button type="button" aria-label="기울임" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg></button>
|
||||
<button type="button" aria-label="밑줄" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 3v7a6 6 0 0 0 12 0V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="글자 색" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.5 14.5 12 3.5l5.5 11"></path><path d="M8.5 10.5h7"></path><rect x="4.5" y="18" width="15" height="3" rx="1" fill="#1F2733" stroke="none"></rect></svg></button>
|
||||
<button type="button" aria-label="배경 색" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="3.5" width="17" height="17" rx="3" fill="none"></rect><path d="M8 16.5 12 7.5l4 9"></path><path d="M9.3 13.5h5.4"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="글머리 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="9" y1="6" x2="20" y2="6"></line><line x1="9" y1="12" x2="20" y2="12"></line><line x1="9" y1="18" x2="20" y2="18"></line><circle cx="4.5" cy="6" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="12" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="18" r="1.2" fill="currentColor" stroke="none"></circle></svg></button>
|
||||
<button type="button" aria-label="번호 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="12"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="링크" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="서식 더보기" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none" aria-hidden="true"><circle cx="5" cy="12" r="1.6"></circle><circle cx="12" cy="12" r="1.6"></circle><circle cx="19" cy="12" r="1.6"></circle></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
</figure>
|
||||
<figure style="margin: 0; display: flex; flex-direction: column; gap: 6px">
|
||||
<figcaption style="font-size: 12.5px; font-weight: 600; color: #344054">쓰기 칸 340px (휴대폰)</figcaption>
|
||||
<div style="width: 340px; box-sizing: border-box; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF">
|
||||
<div style="display: flex; align-items: center; gap: 2px; min-height: 52px; box-sizing: border-box; padding: 4px 20px">
|
||||
<button type="button" aria-label="굵게" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<button type="button" aria-label="기울임" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg></button>
|
||||
<button type="button" aria-label="밑줄" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 3v7a6 6 0 0 0 12 0V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="글머리 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="9" y1="6" x2="20" y2="6"></line><line x1="9" y1="12" x2="20" y2="12"></line><line x1="9" y1="18" x2="20" y2="18"></line><circle cx="4.5" cy="6" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="12" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="18" r="1.2" fill="currentColor" stroke="none"></circle></svg></button>
|
||||
<button type="button" aria-label="번호 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="12"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-haspopup="menu" aria-expanded="true" aria-label="서식 더보기" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: #F2F4F7; color: #171C26; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none" aria-hidden="true"><circle cx="5" cy="12" r="1.6"></circle><circle cx="12" cy="12" r="1.6"></circle><circle cx="19" cy="12" r="1.6"></circle></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
</figure>
|
||||
<ol style="margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: #344054">
|
||||
<li>실행 취소 · 다시 실행 — 쓰기 칸 734px 미만 (Ctrl+Z · Ctrl+Y 는 그대로)</li>
|
||||
<li>글꼴 · 글자 크기 — 639px 미만</li>
|
||||
<li>글자 색 · 배경 색 — 460px 미만</li>
|
||||
<li>링크 — 365px 미만 (주소를 붙여 넣으면 저절로 링크가 된다)</li>
|
||||
<li>글머리 · 번호 목록 — 312px 미만</li>
|
||||
</ol>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">굵게 · 기울임 · 밑줄과 더보기는 늘 남습니다. 폭은 지금 크기로 셈한 참고값이고, 구현은 툴바의 실제 폭을 재어(ResizeObserver) 이 순서로 넘깁니다.</p>
|
||||
</div>
|
||||
<figure style="flex: 1 1 auto; min-width: 0; margin: 0; display: flex; flex-direction: column; gap: 6px">
|
||||
<figcaption style="font-size: 12.5px; font-weight: 600; color: #344054">340px 에서 연 더보기 (위쪽)</figcaption>
|
||||
<div role="menu" aria-label="서식 더보기 (예시)" style="width: 220px; box-sizing: border-box; padding: 6px; display: flex; flex-direction: column; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<button type="button" role="menuitem" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M9 14 4 9l5-5"></path><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"></path></svg><span style="flex: 1 1 auto">실행 취소</span><span style="font-size: 12px; color: #667085">Ctrl+Z</span></button>
|
||||
<button type="button" role="menuitem" disabled="{{ true }}" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; opacity: 0.5"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="m15 14 5-5-5-5"></path><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"></path></svg><span style="flex: 1 1 auto">다시 실행</span><span style="font-size: 12px; color: #667085">Ctrl+Y</span></button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<button type="button" role="menuitem" aria-haspopup="menu" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><polyline points="4 7 4 4 20 4 20 7"></polyline><line x1="9" y1="20" x2="15" y2="20"></line><line x1="12" y1="4" x2="12" y2="20"></line></svg><span style="flex: 1 1 auto">글꼴</span><span style="font-size: 12px; color: #667085">맑은 고딕</span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg></button>
|
||||
<button type="button" role="menuitem" aria-haspopup="menu" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M3 7V5h10v2"></path><path d="M8 5v14"></path><path d="M6 19h4"></path><path d="M14 12v-1h7v1"></path><path d="M17.5 11v8"></path><path d="M16 19h3"></path></svg><span style="flex: 1 1 auto">글자 크기</span><span style="font-size: 12px; color: #667085">14</span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg></button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<button type="button" role="menuitemcheckbox" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M16 4H9a3 3 0 0 0-2.83 4"></path><path d="M14 12a4 4 0 0 1 0 8H6"></path><line x1="4" y1="12" x2="20" y2="12"></line></svg><span style="flex: 1 1 auto">취소선</span><span style="font-size: 12px; color: #667085">Ctrl+Shift+S</span></button>
|
||||
<button type="button" role="menuitem" aria-haspopup="dialog" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M6.5 14.5 12 3.5l5.5 11"></path><path d="M8.5 10.5h7"></path><rect x="4.5" y="18" width="15" height="3" rx="1" fill="#1F2733" stroke="none"></rect></svg><span style="flex: 1 1 auto">글자 색</span><span style="font-size: 12px; color: #667085">기본</span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg></button>
|
||||
<button type="button" role="menuitem" aria-haspopup="dialog" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><rect x="3.5" y="3.5" width="17" height="17" rx="3" fill="none"></rect><path d="M8 16.5 12 7.5l4 9"></path><path d="M9.3 13.5h5.4"></path></svg><span style="flex: 1 1 auto">배경 색</span><span style="font-size: 12px; color: #667085">없음</span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg></button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<p style="margin: 0; padding: 6px 10px 4px; font-size: 12px; line-height: 1.5; color: #667085">아래로 정렬 · 들여쓰기 · 링크 넣기 · 인용 · 표 · 가로줄 · 서식 지우기. 화면 높이에 맞춰 안에서 스크롤</p>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">값을 고르는 것(글꼴 · 크기 · 색)은 › 로 한 단계 더 엽니다.</p>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">빈 본문</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">새 메일처럼 본문이 비었을 때 (커서가 본문에 있는 상태)</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF; overflow: hidden">
|
||||
<div style="display: flex; align-items: center; gap: 2px; min-height: 52px; box-sizing: border-box; padding: 4px 20px; border-bottom: 1px solid #EEF0F3">
|
||||
<button type="button" aria-label="굵게" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 4h8a4 4 0 0 1 0 8H6z"></path><path d="M6 12h9a4 4 0 0 1 0 8H6z"></path></svg></button>
|
||||
<button type="button" aria-label="기울임" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg></button>
|
||||
<button type="button" aria-label="밑줄" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 3v7a6 6 0 0 0 12 0V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="글머리 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="9" y1="6" x2="20" y2="6"></line><line x1="9" y1="12" x2="20" y2="12"></line><line x1="9" y1="18" x2="20" y2="18"></line><circle cx="4.5" cy="6" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="12" r="1.2" fill="currentColor" stroke="none"></circle><circle cx="4.5" cy="18" r="1.2" fill="currentColor" stroke="none"></circle></svg></button>
|
||||
<button type="button" aria-label="번호 목록" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="12"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="링크" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-label="서식 더보기" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none" aria-hidden="true"><circle cx="5" cy="12" r="1.6"></circle><circle cx="12" cy="12" r="1.6"></circle><circle cx="19" cy="12" r="1.6"></circle></svg></button>
|
||||
</div>
|
||||
<div style="min-height: 120px; box-sizing: border-box; padding: 16px 32px; border-bottom: 1px solid #0E7C86; box-shadow: inset 0 -1px 0 #0E7C86; font-family: 'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif; font-size: 14px; line-height: 1.75">
|
||||
<p style="margin: 0; display: flex; align-items: center; color: #667085"><span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 18px; margin-right: 1px; background: #171C26"></span>내용을 입력하세요</p>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 6px; min-height: 44px; box-sizing: border-box; padding: 0 32px 0 26px; color: #344054; font-weight: 500">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="margin-left: 6px"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>
|
||||
<span>파일 첨부</span>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">안내 문구는 지금과 같은 "내용을 입력하세요" · #667085 (흰 바탕 4.9:1). 한 글자라도 쓰면 사라지고, 커서는 문구 앞에 선다.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; align-items: start">
|
||||
|
||||
<section style="min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">더보기 메뉴</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">800px — 툴바에 없는 서식 · 항목 높이 40 (밀도 예외 · 사용자 확정)</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: flex-end; gap: 4px">
|
||||
<div style="align-self: stretch; display: flex; justify-content: flex-end; align-items: center; gap: 2px; min-height: 52px; box-sizing: border-box; padding: 4px 0; border-bottom: 1px solid #EEF0F3">
|
||||
<button type="button" aria-label="링크" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #344054; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></button>
|
||||
<span aria-hidden="true" style="flex: 0 0 auto; width: 1px; height: 20px; margin: 0 4px; background: #E6E8EC"></span>
|
||||
<button type="button" aria-haspopup="menu" aria-expanded="true" aria-label="서식 더보기" style="width: 40px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: #F2F4F7; color: #171C26; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none" aria-hidden="true"><circle cx="5" cy="12" r="1.6"></circle><circle cx="12" cy="12" r="1.6"></circle><circle cx="19" cy="12" r="1.6"></circle></svg></button>
|
||||
</div>
|
||||
<div role="menu" aria-label="서식 더보기 (예시)" style="width: 256px; box-sizing: border-box; padding: 6px; display: flex; flex-direction: column; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<button type="button" role="menuitemcheckbox" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M16 4H9a3 3 0 0 0-2.83 4"></path><path d="M14 12a4 4 0 0 1 0 8H6"></path><line x1="4" y1="12" x2="20" y2="12"></line></svg><span style="flex: 1 1 auto">취소선</span><span style="font-size: 12px; color: #667085">Ctrl+Shift+S</span><span style="flex: 0 0 auto; width: 16px; height: 16px"></span></button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<button type="button" role="menuitemradio" aria-checked="true" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="17" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="17" y1="18" x2="3" y2="18"></line></svg><span style="flex: 1 1 auto">왼쪽 정렬</span><span style="font-size: 12px; color: #667085">Ctrl+Shift+L</span><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="20 6 9 17 4 12"></polyline></svg></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: #F2F4F7; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="18" y1="10" x2="6" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="18" y1="18" x2="6" y2="18"></line></svg><span style="flex: 1 1 auto">가운데 정렬</span><span style="font-size: 12px; color: #667085">Ctrl+Shift+E</span><span style="flex: 0 0 auto; width: 16px; height: 16px"></span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="21" y1="10" x2="7" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="21" y1="18" x2="7" y2="18"></line></svg><span style="flex: 1 1 auto">오른쪽 정렬</span><span style="font-size: 12px; color: #667085">Ctrl+Shift+R</span><span style="flex: 0 0 auto; width: 16px; height: 16px"></span></button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<button type="button" role="menuitem" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><polyline points="7 8 3 12 7 16"></polyline><line x1="21" y1="12" x2="11" y2="12"></line><line x1="21" y1="6" x2="11" y2="6"></line><line x1="21" y1="18" x2="11" y2="18"></line></svg><span style="flex: 1 1 auto">내어쓰기</span><span style="font-size: 12px; color: #667085">Ctrl+[</span><span style="flex: 0 0 auto; width: 16px; height: 16px"></span></button>
|
||||
<button type="button" role="menuitem" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><polyline points="3 8 7 12 3 16"></polyline><line x1="21" y1="12" x2="11" y2="12"></line><line x1="21" y1="6" x2="11" y2="6"></line><line x1="21" y1="18" x2="11" y2="18"></line></svg><span style="flex: 1 1 auto">들여쓰기</span><span style="font-size: 12px; color: #667085">Ctrl+]</span><span style="flex: 0 0 auto; width: 16px; height: 16px"></span></button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<button type="button" role="menuitemcheckbox" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M17 6H3"></path><path d="M21 12H8"></path><path d="M21 18H8"></path><path d="M3 12v6"></path></svg><span style="flex: 1 1 auto">인용</span><span style="font-size: 12px; color: #667085">Ctrl+Shift+B</span><span style="flex: 0 0 auto; width: 16px; height: 16px"></span></button>
|
||||
<button type="button" role="menuitem" aria-haspopup="dialog" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="3" y1="15" x2="21" y2="15"></line><line x1="9" y1="3" x2="9" y2="21"></line><line x1="15" y1="3" x2="15" y2="21"></line></svg><span style="flex: 1 1 auto">표 넣기</span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; margin: 0 1px; color: #667085"><polyline points="9 18 15 12 9 6"></polyline></svg></button>
|
||||
<button type="button" role="menuitem" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><line x1="3" y1="12" x2="21" y2="12"></line><polyline points="8 8 12 4 16 8"></polyline><polyline points="16 16 12 20 8 16"></polyline></svg><span style="flex: 1 1 auto">가로줄</span><span style="flex: 0 0 auto; width: 16px; height: 16px"></span></button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<button type="button" role="menuitem" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto; color: #4A5363"><path d="M4 7V4h16v3"></path><path d="M5 20h6"></path><path d="M13 4 8 20"></path><path d="m15 15 5 5"></path><path d="m20 15-5 5"></path></svg><span style="flex: 1 1 auto">서식 지우기</span><span style="font-size: 12px; color: #667085">Ctrl+\</span><span style="flex: 0 0 auto; width: 16px; height: 16px"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">켜진 서식은 오른쪽 ✓ (취소선 · 정렬 · 인용). 단축키는 흐린 글자. 올린 항목은 #F2F4F7 (가운데 정렬).</p>
|
||||
</section>
|
||||
|
||||
<section style="min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">글꼴 · 글자 크기</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">받는 쪽에 흔히 있는 글꼴만 — 이름은 그 글꼴로 보입니다</p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 16px; align-items: flex-start">
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<button type="button" aria-haspopup="menu" aria-expanded="true" aria-label="글꼴: 맑은 고딕" style="width: 108px; height: 44px; display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; padding: 0 8px 0 12px; border: 0; border-radius: 8px; background: #F2F4F7; color: #171C26; font: inherit; font-weight: 500; cursor: pointer"><span style="flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left">맑은 고딕</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
|
||||
<div role="menu" aria-label="글꼴 (예시)" style="width: 216px; box-sizing: border-box; padding: 6px; display: flex; flex-direction: column; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<button type="button" role="menuitemradio" aria-checked="true" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: 'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">맑은 고딕</span><span style="flex: 0 0 auto; font-family: Pretendard, -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', system-ui, sans-serif; font-size: 12px; color: #667085">기본</span><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="20 6 9 17 4 12"></polyline></svg></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: Gulim, '굴림', sans-serif; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">굴림</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: Dotum, '돋움', sans-serif; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">돋움</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: Batang, '바탕', serif; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">바탕</span></button>
|
||||
<hr style="width: 100%; height: 1px; margin: 4px 0; border: 0; background: #EEF0F3">
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: Arial, sans-serif; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">Arial</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: Verdana, sans-serif; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">Verdana</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: Georgia, serif; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">Georgia</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: 'Times New Roman', serif; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">Times New Roman</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; font-size: 14px; font-family: 'Courier New', monospace; text-align: left; cursor: pointer"><span style="flex: 1 1 auto">Courier New</span></button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<button type="button" aria-haspopup="menu" aria-expanded="true" aria-label="글자 크기: 14" style="width: 56px; height: 44px; display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; padding: 0 8px 0 12px; border: 0; border-radius: 8px; background: #F2F4F7; color: #171C26; font: inherit; font-weight: 500; cursor: pointer"><span style="flex: 1 1 auto; text-align: left">14</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
|
||||
<div role="menu" aria-label="글자 크기 (예시)" style="width: 124px; box-sizing: border-box; padding: 6px; display: flex; flex-direction: column; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><span style="flex: 1 1 auto; font-size: 12px; line-height: 1.1">12</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><span style="flex: 1 1 auto; font-size: 13px; line-height: 1.1">13</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="true" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><span style="flex: 1 1 auto; font-size: 14px; line-height: 1.1">14</span><span style="font-size: 12px; color: #667085">기본</span><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0A5F67" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="20 6 9 17 4 12"></polyline></svg></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><span style="flex: 1 1 auto; font-size: 16px; line-height: 1.1">16</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><span style="flex: 1 1 auto; font-size: 18px; line-height: 1.1">18</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><span style="flex: 1 1 auto; font-size: 20px; line-height: 1.1">20</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><span style="flex: 1 1 auto; font-size: 24px; line-height: 1.1">24</span></button>
|
||||
<button type="button" role="menuitemradio" aria-checked="false" style="display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: 6px; background: transparent; color: #171C26; font: inherit; text-align: left; cursor: pointer"><span style="flex: 1 1 auto; font-size: 32px; line-height: 1.1">32</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">맑은 고딕이 본문 기본 글꼴이라 받는 쪽에서도 같은 모양입니다(맥에서는 Apple SD 산돌고딕 Neo). 크기는 px 숫자 · 기본 14 · 제목 스타일은 두지 않습니다. 고른 글자의 크기가 섞이면 "–".</p>
|
||||
</section>
|
||||
|
||||
<section style="min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">글자 색 · 배경 색</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">8색씩 — 글자 색은 모두 흰 바탕 4.5:1 이상</p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 16px; align-items: flex-start">
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<button type="button" aria-haspopup="dialog" aria-expanded="true" aria-label="글자 색: 빨강" style="width: 40px; height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: #F2F4F7; color: #171C26; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.5 14.5 12 3.5l5.5 11"></path><path d="M8.5 10.5h7"></path><rect x="4.5" y="18" width="15" height="3" rx="1" fill="#B42318" stroke="none"></rect></svg></button>
|
||||
<div role="dialog" aria-label="글자 색 (예시)" style="width: 186px; box-sizing: border-box; padding: 10px; display: flex; flex-direction: column; gap: 8px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<div style="display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 0 2px"><span style="font-size: 12.5px; font-weight: 600; color: #4A5363">글자 색</span><span style="font-size: 12px; color: #667085">빨강</span></div>
|
||||
<div style="display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px">
|
||||
<button type="button" aria-label="기본" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #1F2733; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="회색" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #667085; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="빨강" aria-pressed="true" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; background: #B42318; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14); color: #FFFFFF"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></span></button>
|
||||
<button type="button" aria-label="주황" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #B54708; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="초록" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #067647; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="청록" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #0E7C86; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="파랑" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #175CD3; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="보라" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #6941C6; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<button type="button" aria-haspopup="dialog" aria-expanded="true" aria-label="배경 색: 노랑" style="width: 40px; height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: #F2F4F7; color: #171C26; cursor: pointer"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="3.5" width="17" height="17" rx="3" fill="#FFF1A8"></rect><path d="M8 16.5 12 7.5l4 9"></path><path d="M9.3 13.5h5.4"></path></svg></button>
|
||||
<div role="dialog" aria-label="배경 색 (예시)" style="width: 186px; box-sizing: border-box; padding: 10px; display: flex; flex-direction: column; gap: 8px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<div style="display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 0 2px"><span style="font-size: 12.5px; font-weight: 600; color: #4A5363">배경 색</span><span style="font-size: 12px; color: #667085">노랑</span></div>
|
||||
<div style="display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px">
|
||||
<button type="button" aria-label="없음" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; background: #FFFFFF; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#B42318" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="5" y1="19" x2="19" y2="5"></line></svg></span></button>
|
||||
<button type="button" aria-label="노랑" aria-pressed="true" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; background: #FFF1A8; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14); color: #171C26"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg></span></button>
|
||||
<button type="button" aria-label="주황" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #FDE4CC; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="분홍" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #FBDCE3; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="초록" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #D9F2DF; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="하늘" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #D6E8FB; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="보라" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #E9E0FA; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
<button type="button" aria-label="회색" aria-pressed="false" style="width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer"><span style="width: 26px; height: 26px; border-radius: 6px; background: #E9EBEF; box-shadow: inset 0 0 0 1px rgba(16, 24, 40, 0.14)"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">견본 칸 40×40 (보이는 색 26 · 밀도 예외 · 사용자 확정). 고른 색에 ✓ 하고 이름을 위에 글자로도 씁니다. "기본"은 글자 색을, "없음"은 배경 색을 지웁니다.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; align-items: start">
|
||||
|
||||
<section style="grid-column: span 2; min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">답장 · 전달 — 편집기 안의 원문 인용</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">원문은 회색 인용 막대 안에 "원본 메일" 머리와 함께 둡니다(답장 · 전달 모두). 내 글은 그 위에 씁니다.</p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 16px; align-items: flex-start">
|
||||
<figure style="flex: 1 1 500px; min-width: 0; margin: 0; display: flex; flex-direction: column; gap: 6px">
|
||||
<div style="box-sizing: border-box; padding: 16px 32px; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF; font-family: 'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif; font-size: 14px; line-height: 1.75; color: #1F2733">
|
||||
<p style="margin: 0">도윤님, 확인했습니다.</p>
|
||||
<p style="margin: 0">체크리스트 기준으로 <strong>금요일 저녁 전환</strong>을 진행해 주세요.</p>
|
||||
<p style="margin: 0"> </p>
|
||||
<p style="margin: 0">김아라</p>
|
||||
<blockquote style="margin: 24px 0 0; padding: 2px 0 2px 14px; border-left: 2px solid #D0D5DD; color: #4A5363">
|
||||
<div style="margin: 0 0 12px; font-size: 12.5px; line-height: 1.6">
|
||||
<p style="margin: 0; font-weight: 600">원본 메일</p>
|
||||
<table style="border-collapse: collapse; font-size: 12.5px; line-height: 1.6">
|
||||
<tbody>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">보낸 사람</th><td style="padding: 0">이도윤 <doyun.lee@arasystem.it.kr></td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">날짜</th><td style="padding: 0">2026. 10. 26. (월) 오전 10:42</td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">제목</th><td style="padding: 0">Re: 메일 서버 이전 일정 공유</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p style="margin: 0">김아라님, 안녕하세요.</p>
|
||||
<p style="margin: 0"> </p>
|
||||
<p style="margin: 0">말씀하신 대로 이번 주 금요일(10/30) 저녁 9시에 MX 레코드를 새 메일 서버로 전환하겠습니다.</p>
|
||||
<p style="margin: 0; color: #98A2B3" aria-hidden="true">…</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
<figcaption style="font-size: 12.5px; color: #344054"><strong style="font-weight: 600">답장</strong> — 보낸 사람 · 날짜 · 제목. 커서는 맨 위 첫 줄</figcaption>
|
||||
</figure>
|
||||
<figure style="flex: 0 1 320px; min-width: 0; margin: 0; display: flex; flex-direction: column; gap: 6px">
|
||||
<div style="box-sizing: border-box; padding: 16px 20px 16px 24px; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF; font-family: 'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif; font-size: 14px; line-height: 1.75; color: #1F2733">
|
||||
<p style="margin: 0"> </p>
|
||||
<blockquote style="margin: 24px 0 0; padding: 2px 0 2px 14px; border-left: 2px solid #D0D5DD; color: #4A5363">
|
||||
<div style="margin: 0 0 12px; font-size: 12.5px; line-height: 1.6">
|
||||
<p style="margin: 0; font-weight: 600">원본 메일</p>
|
||||
<table style="border-collapse: collapse; font-size: 12.5px; line-height: 1.6">
|
||||
<tbody>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">보낸 사람</th><td style="padding: 0; overflow-wrap: anywhere">이도윤 <doyun.lee@arasystem.it.kr></td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">날짜</th><td style="padding: 0">2026. 10. 26. (월) 오전 10:42</td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">받는 사람</th><td style="padding: 0; overflow-wrap: anywhere">김아라 <ara.kim@arasystem.it.kr></td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">참조</th><td style="padding: 0; overflow-wrap: anywhere">인프라팀 <infra@arasystem.it.kr></td></tr>
|
||||
<tr><th scope="row" style="padding: 0 12px 0 0; text-align: left; vertical-align: top; font-weight: 400; color: #667085; white-space: nowrap">제목</th><td style="padding: 0">Re: 메일 서버 이전 일정 공유</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p style="margin: 0">김아라님, 안녕하세요.</p>
|
||||
<p style="margin: 0; color: #98A2B3" aria-hidden="true">…</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
<figcaption style="font-size: 12.5px; color: #344054"><strong style="font-weight: 600">전달</strong> — 받는 사람 · 참조가 더해진다. 커서는 받는 사람 칸</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">인용 막대 2px #D0D5DD · 막대와 글 사이 14 · 원문 글 #4A5363 · 머리 12.5px(항목 이름 #667085) · 내 글과 24 띄움. 막대를 회색으로 둔 것은 2px 브랜드색 선(포커스)과 헷갈리지 않게 하려는 것. 툴바의 "인용"도 같은 막대를 머리 없이 쓴다.</p>
|
||||
</section>
|
||||
|
||||
<section style="min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">링크</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">주소와 표시할 글자 — 이미 있는 링크를 고칠 때</p>
|
||||
</div>
|
||||
<p style="margin: 0; font-family: 'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif; font-size: 14px; line-height: 1.75; color: #1F2733">진행 상황은 <span style="background: #D6E8FB; color: #0E7C86; text-decoration: underline">전환 안내 페이지</span>에서 볼 수 있습니다.</p>
|
||||
<div role="dialog" aria-label="링크 고치기 (예시)" style="width: 300px; max-width: 100%; box-sizing: border-box; padding: 14px; display: flex; flex-direction: column; gap: 10px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<label for="ex-link-url" style="font-size: 12.5px; font-weight: 600; color: #344054">주소</label>
|
||||
<input id="ex-link-url" type="url" value="https://wiki.arasystem.it.kr/mail-migration" readonly style="min-height: 40px; box-sizing: border-box; padding: 0 12px; border: 1px solid #8A94A3; border-radius: 8px; font: inherit; color: #171C26; background: #FFFFFF; outline: 2px solid #0E7C86; outline-offset: 2px">
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 4px">
|
||||
<label for="ex-link-text" style="font-size: 12.5px; font-weight: 600; color: #344054">표시할 글자</label>
|
||||
<input id="ex-link-text" type="text" value="전환 안내 페이지" readonly style="min-height: 40px; box-sizing: border-box; padding: 0 12px; border: 1px solid #8A94A3; border-radius: 8px; font: inherit; color: #171C26; background: #FFFFFF">
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 6px">
|
||||
<button type="button" style="display: inline-flex; align-items: center; gap: 6px; min-height: 44px; margin-left: -6px; padding: 0 8px 0 6px; border: 0; border-radius: 8px; background: transparent; color: #344054; font: inherit; font-weight: 500; cursor: pointer"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m18.84 12.25 1.72-1.71a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="m5.17 11.75-1.71 1.71a5 5 0 0 0 7.07 7.07l1.71-1.71"></path><line x1="8" y1="2" x2="8" y2="5"></line><line x1="2" y1="8" x2="5" y2="8"></line><line x1="16" y1="19" x2="16" y2="22"></line><line x1="19" y1="16" x2="22" y2="16"></line></svg><span>링크 빼기</span></button>
|
||||
<span style="flex: 1 1 auto"></span>
|
||||
<button type="button" style="min-height: 44px; padding: 0 12px; border: 0; border-radius: 8px; background: transparent; color: #344054; font: inherit; font-weight: 500; cursor: pointer">취소</button>
|
||||
<button type="button" style="min-height: 44px; padding: 0 16px; border: 0; border-radius: 8px; background: #0E7C86; color: #FFFFFF; font: inherit; font-weight: 600; cursor: pointer">적용</button>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">Enter = 적용 · Esc = 닫고 본문으로. 새 링크는 "링크 빼기" 없이 "넣기". 주소는 http(s) · mailto 만. 상자 입력칸이라 포커스는 고리(주소 칸).</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; align-items: start">
|
||||
|
||||
<section style="grid-column: span 2; min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">본문에 넣은 이미지 → 첨부 파일</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">본문에는 이미지를 넣지 않습니다(사용자 확정). 붙여 넣거나 끌어다 놓은 이미지는 첨부 파일로 올리고, 툴바에는 이미지 버튼이 없습니다.</p>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; align-items: start">
|
||||
<figure style="margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 6px">
|
||||
<figcaption style="font-size: 12.5px; font-weight: 600; color: #344054">① 끌어다 놓는 중</figcaption>
|
||||
<div style="position: relative; height: 150px; box-sizing: border-box; padding: 12px 16px; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF; overflow: hidden; font-family: 'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif; font-size: 14px; line-height: 1.75; color: #1F2733">
|
||||
<p style="margin: 0">화면 캡처 함께 보냅니다.</p>
|
||||
<div aria-hidden="true" style="position: absolute; inset: 8px; display: flex; align-items: center; justify-content: center; gap: 8px; border: 2px dashed #0E7C86; border-radius: 8px; background: rgba(243, 248, 248, 0.94); color: #0A5F67; font-family: Pretendard, -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', system-ui, sans-serif; font-size: 13px; font-weight: 600">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>
|
||||
<span>놓으면 첨부 파일로 올립니다</span>
|
||||
</div>
|
||||
</div>
|
||||
</figure>
|
||||
<figure style="margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 6px">
|
||||
<figcaption style="font-size: 12.5px; font-weight: 600; color: #344054">② 첨부 목록에 올라간다</figcaption>
|
||||
<div style="display: flex; flex-direction: column; gap: 6px; padding: 8px 12px 12px; border: 1px solid #E6E8EC; border-radius: 8px; background: #FFFFFF">
|
||||
<span style="display: inline-flex; align-items: center; gap: 6px; min-height: 32px; color: #344054; font-weight: 500"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>파일 첨부</span>
|
||||
<span style="font-size: 12px; color: #667085">파일당 최대 20MB · 합계 25MB · 최대 20개 · 문서, 이미지, 압축 파일</span>
|
||||
<ul style="list-style: none; margin: 2px 0 0; padding: 0">
|
||||
<li style="display: flex; flex-direction: column; gap: 4px; padding: 2px 2px 2px 10px; border: 1px solid #E6E8EC; border-radius: 8px">
|
||||
<div style="display: flex; align-items: center; gap: 10px">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#4A5363" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
|
||||
<span style="flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500">image.png</span>
|
||||
<span style="flex: 0 0 auto; font-size: 12px; color: #667085; font-variant-numeric: tabular-nums">올리는 중 62%</span>
|
||||
<button type="button" aria-label="image.png 첨부 취소" style="flex: 0 0 auto; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 6px; background: transparent; color: #4A5363; cursor: pointer"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button>
|
||||
</div>
|
||||
<div style="width: calc(100% - 8px); height: 3px; margin: 0 0 6px; border-radius: 2px; background: #E4E7EC"><div style="width: 62%; height: 3px; border-radius: 2px; background: #0E7C86"></div></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</figure>
|
||||
<figure style="margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 6px">
|
||||
<figcaption style="font-size: 12.5px; font-weight: 600; color: #344054">③ 이미지였으면 알린다</figcaption>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 6px 6px 6px 14px; border-radius: 10px; background: #0B3640; color: #FFFFFF; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.22)">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#9FE0B5" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex: 0 0 auto"><polyline points="20 6 9 17 4 12"></polyline></svg>
|
||||
<span style="flex: 1 1 auto; font-weight: 500">이미지는 본문 대신 첨부 파일로 올렸습니다.</span>
|
||||
<button type="button" aria-label="알림 닫기" style="flex: 0 0 auto; width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 6px; background: transparent; color: #A3C2C6; cursor: pointer"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">성공 알림과 같은 모양 · 5초 뒤 닫힌다</p>
|
||||
</figure>
|
||||
</div>
|
||||
<ul style="margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: #4A5363">
|
||||
<li>붙여 넣기(Ctrl+V) · 끌어다 놓기 모두. 끌어다 놓은 다른 파일도 첨부로 올린다 — 알림은 이미지를 돌렸을 때만.</li>
|
||||
<li>한도는 첨부와 같다. 넘치면 첨부 목록에 실패로 보인다 (오류 · 빈 상태 보드의 "첨부 업로드").</li>
|
||||
<li>끌어다 놓는 동안의 덮개는 2px #0E7C86 점선 · 바탕 #F3F8F8 — 포커스 선(실선)과 모양이 다르다.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section style="min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 20px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 12px">
|
||||
<div style="display: flex; flex-direction: column; gap: 2px">
|
||||
<h2 style="margin: 0; font-size: 14px; font-weight: 700">표 넣기</h2>
|
||||
<p style="margin: 0; font-size: 12px; color: #667085">더보기 › 표 넣기 — 행 · 열을 고릅니다</p>
|
||||
</div>
|
||||
<div role="dialog" aria-label="표 넣기 (예시)" style="align-self: flex-start; box-sizing: border-box; padding: 12px; display: flex; flex-direction: column; gap: 8px; background: #FFFFFF; border: 1px solid #E6E8EC; border-radius: 10px; box-shadow: 0 10px 28px rgba(16, 24, 28, 0.12)">
|
||||
<span style="font-size: 12.5px; font-weight: 600; color: #4A5363">표 넣기</span>
|
||||
<div aria-hidden="true" style="display: grid; grid-template-columns: repeat(8, 22px); gap: 3px">
|
||||
<span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span>
|
||||
<span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span>
|
||||
<span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #0E7C86; border-radius: 3px; background: #E3F2F3"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span>
|
||||
<span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span>
|
||||
<span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span>
|
||||
<span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span><span style="width: 22px; height: 22px; box-sizing: border-box; border: 1px solid #D0D5DD; border-radius: 3px; background: #FFFFFF"></span>
|
||||
</div>
|
||||
<span style="font-size: 12.5px; color: #344054; font-variant-numeric: tabular-nums">3행 × 4열</span>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 12px; color: #4A5363">칸 22px · 간격 3 (밀도 예외 · 사용자 확정). 마우스는 칸 위로 움직여 고르고 누르면 넣습니다. 키보드는 화살표 + Enter. 표 안의 행 · 열 추가와 삭제는 다음 단계.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":1440,"height":3576}}'>
|
||||
class Component extends DCLogic {
|
||||
renderVals() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
확정된 디자인 캔버스의 원본이다. 화면 구현의 기준으로 쓴다.
|
||||
|
||||
- 캔버스: https://claude.ai/artifact/WJvVsKvXepxn3p75CGJAr2 (확정본: 2026-10-26, 버전 11)
|
||||
- 캔버스: https://claude.ai/artifact/WJvVsKvXepxn3p75CGJAr2 (확정본: 2026-10-27, 버전 14)
|
||||
- 화면: `Login`(로그인) · `Main`(분할 보기: 메일함·목록·본문) · `MainList`(목록 보기: 게시판형 표) · `MainListRead`(목록 보기에서 연 메일)
|
||||
· `Compose`(메일 쓰기) · `States`(오류·빈 상태·피드백 모음)
|
||||
· `Compose`(메일 쓰기 — 서식 편집기) · `ComposeEditor`(메일 쓰기 · 편집기 상태: 포커스·툴바·메뉴·팝오버·인용·이미지 첨부)
|
||||
· `States`(오류·빈 상태·피드백 모음)
|
||||
- 파일 형식은 캔버스 전용(`<x-dc>` 마크업 + `DCLogic` 클래스)이다. 그대로 쓰지 말고 **구조·간격·색·문구의 기준**으로만 본다.
|
||||
`Compose` 의 툴바·메뉴는 눌러 볼 수 있는 시안이다 — 버튼 상태만 바뀌고 본문 글자에 서식이 입혀지지는 않는다.
|
||||
|
||||
## 캔버스 안의 자산 주소
|
||||
|
||||
@@ -28,16 +30,119 @@
|
||||
- 목록 보기 행: 1줄 표, 38px. 칸 = 별 32 · 보낸 사람 168 · 제목(나머지) · 날짜 84 · 크기 64 (px, 칸 사이 12).
|
||||
폭 1100px 미만에서 크기 칸 숨김, 600px 미만에서 보낸 사람·날짜 축소, 더 좁으면 가로 스크롤.
|
||||
캔버스는 파서 제약 때문에 grid 로 그렸지만 **구현은 실제 `<table>`** 로 한다.
|
||||
- 별 버튼·"분할 | 목록" 전환은 밀도를 위해 32~36px 로 둔다(클릭 영역 44px 기준의 의도된 예외 — 사용자 확정).
|
||||
- **클릭 영역은 44px 이 기본**이다. 아래만 밀도를 위한 의도된 예외다(사용자 확정).
|
||||
- 목록 표의 별 버튼(폭 32px) · "분할 | 목록" 전환(바깥 36px)
|
||||
- 메일 쓰기 편집기(2026-10-27): 툴바 아이콘 버튼 40×44(새로고침·이전/다음 버튼과 같은 크기) · 메뉴 항목 높이 40(메일함 항목과 같다)
|
||||
· 색 견본 칸 40×40 · 표 고르기 격자 칸 22(간격 3, 키보드는 화살표)
|
||||
- 보기 방식: 목록 머리의 "분할 | 목록" 전환. 선택은 사용자별로 기억한다.
|
||||
- **콘텐츠 열(읽기·쓰기 공통)**: 최대 폭 800px, 좌우 여백 32px, 위 20px·아래 36px, 본문 글줄 최대 680px, 영역 안 왼쪽 정렬.
|
||||
분할 보기 읽기·목록 보기 읽기·쓰기 세 곳이 같은 값을 쓰고, 툴바 첫 아이콘도 같은 32px 선에서 시작한다.
|
||||
- 브랜드 컬러 "바다 청록": 바탕 `#0B3640`, 강조 `#0E7C86`. 파생 색은 각 화면 원본의 인라인 스타일을 따른다.
|
||||
|
||||
## 메일 쓰기 (2026-10-27 확정 — `Compose` · `ComposeEditor`)
|
||||
|
||||
위에서부터 머리(제목·닫기) → 받는 사람(→ 참조·숨은참조) → 제목 → 본문 툴바 → 본문 → 첨부 → 보내기 줄이다. 모두 콘텐츠 열 안에 있다.
|
||||
첨부 안내문은 "파일당 최대 20MB · 합계 25MB · 최대 20개 · 문서, 이미지, 압축 파일" 이다(용량은 서버 값, 개수는 계약 상수).
|
||||
|
||||
### 글자 입력칸 포커스 — 한 가지 규칙
|
||||
|
||||
| 항목 | 값 |
|
||||
| --- | --- |
|
||||
| 대상 | 받는 사람 · 참조 · 숨은참조 · 제목 · 본문 편집기 |
|
||||
| 위치 | 그 칸의 아래 hairline 자리. 본문은 편집 영역 아래(첨부 영역 위) |
|
||||
| 두께 · 색 | 2px `--color-brand`(#0E7C86). 1px 선의 색을 바꾸고 안쪽 그림자 1px 를 더한다 — 높이가 변하지 않는다 |
|
||||
| 모서리 | 없음(곧은 선) |
|
||||
| 범위 | 행 전체 폭 — 원래 hairline 과 같은 길이(콘텐츠 열, 최대 800px). 이름표 아래까지 이어진다 |
|
||||
| 언제 | 글자 입력 요소(input·편집 영역)에 포커스가 있을 때. 마우스로 눌러도 보인다(`:focus`) |
|
||||
| 대비 | 흰 바탕 4.9:1 · 원래 선 #EEF0F3 4.3:1 · 오류 띠 #FEF3F2 4.5:1 (모두 3:1 이상) |
|
||||
|
||||
- **버튼 고리와의 관계**: 같은 색·같은 2px 이고 모양만 다르다. 누르는 것(버튼·링크)은 전역 `:focus-visible` 고리(바깥 2px, 버튼 모서리를 따른다),
|
||||
쓰는 곳은 선이다. 행 안의 버튼(받는 사람 토큰 ✕ · "참조 · 숨은참조")에 포커스가 가면 고리만 보이고 행의 선은 회색 그대로다 — 한 번에 하나만 보인다.
|
||||
- 테두리가 있는 입력칸(링크 팝오버·로그인)은 상자가 있으므로 버튼처럼 고리를 쓴다.
|
||||
- 구현(tokens.css 변수):
|
||||
|
||||
```css
|
||||
.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; }
|
||||
```
|
||||
|
||||
`.compose-field` 는 받는 사람·참조·숨은참조 행, 제목 행, 본문 편집 영역에 붙인다. 편집 영역이 아래 hairline 을 가지므로 첨부 영역의 위 선은 없앤다.
|
||||
|
||||
### 본문 서식 편집기 (TipTap)
|
||||
|
||||
- **툴바**: 한 줄 · 높이 52(위아래 4) · 왼쪽 여백 20 + 버튼 안 12 → 첫 아이콘이 32px 선. 버튼 사이 2, 묶음 사이 세로선 1×20 #E6E8EC(좌우 4).
|
||||
- 아이콘 버튼 40×44 · 모서리 8 · 아이콘 16(선 1.75) · #344054. 글꼴 108×44 · 글자 크기 56×44(글자 + ▾).
|
||||
- 상태: 올림 #F2F4F7 · 켜짐(`aria-pressed`) #E3F2F3 + 안쪽 1px #0E7C86 + 아이콘 #0A5F67(옅은 바탕만으로는 3:1 이 안 돼 선을 둔다)
|
||||
· 비활성 50% · 포커스는 전역 고리 · 메뉴 열림(`aria-expanded`)은 올림과 같은 바탕.
|
||||
- `role="toolbar"` — Tab 한 번에 들어가 화살표로 옮긴다. 본문에서 Alt+F10 → 툴바, Esc → 본문.
|
||||
- **툴바 기능(800px)**: 실행 취소 · 다시 실행 | 글꼴 ▾ · 글자 크기 ▾ | 굵게 · 기울임 · 밑줄 | 글자 색 · 배경 색 | 글머리 목록 · 번호 목록 | 링크 | 더보기
|
||||
- **더보기(늘)**: 취소선 | 왼쪽 · 가운데 · 오른쪽 정렬 | 내어쓰기 · 들여쓰기 | 인용 · 표 넣기 › · 가로줄 | 서식 지우기
|
||||
- 항목 높이 40 · 아이콘 16 · 이름 · 단축키(12px #667085) · 켜진 것은 오른쪽 ✓. 값을 고르는 것(글꼴·크기·색·표)은 › 로 한 단계 더 연다.
|
||||
- 단축키: 굵게 Ctrl+B · 기울임 Ctrl+I · 밑줄 Ctrl+U · 취소선 Ctrl+Shift+S · 글머리 Ctrl+Shift+8 · 번호 Ctrl+Shift+7 · 정렬 Ctrl+Shift+L/E/R
|
||||
· 내어쓰기 Ctrl+[ · 들여쓰기 Ctrl+] · 인용 Ctrl+Shift+B · 링크 Ctrl+K · 서식 지우기 Ctrl+\ · 실행 취소 Ctrl+Z · 다시 실행 Ctrl+Y
|
||||
- 맥은 Ctrl 대신 ⌘ 이고 표기도 기호로 보인다(⌘B · ⇧⌘S). 다시 실행은 맥 관례대로 ⇧⌘Z 로 적는다(⌘Y 도 된다).
|
||||
내어쓰기 · 들여쓰기 · 서식 지우기는 할 일이 없어도 키를 삼킨다 — 맥의 ⌘[ 가 브라우저 "뒤로"가 되어 쓰던 메일을 잃지 않게 (2026-10-27 구현하며 정함).
|
||||
- **좁은 폭**: 툴바는 줄을 바꾸지 않는다. 묶음째 아래 순서로 더보기에 옮기고, 숨은 묶음은 더보기 맨 위에 툴바 순서대로 들어간다. 더보기 단추에 숫자를 달지 않는다.
|
||||
1. 실행 취소 · 다시 실행 — 쓰기 칸 734px 미만 (Ctrl+Z · Ctrl+Y 는 그대로)
|
||||
2. 글꼴 · 글자 크기 — 639px 미만
|
||||
3. 글자 색 · 배경 색 — 460px 미만
|
||||
4. 링크 — 365px 미만 (주소를 붙여 넣으면 저절로 링크가 된다)
|
||||
5. 글머리 · 번호 목록 — 312px 미만
|
||||
|
||||
굵게 · 기울임 · 밑줄과 더보기는 늘 남는다. 폭은 지금 크기로 셈한 참고값이다 — 구현은 툴바의 실제 폭을 재어(ResizeObserver) 이 순서로 넘긴다.
|
||||
`Compose` 보드의 좁은 폭 메뉴는 색 · 목록을 취소선 뒤에 그렸지만, 이 문서의 순서(숨은 묶음 전부를 맨 위에)가 기준이다 — 구현도 이 순서다.
|
||||
휴대폰에서는 더보기 메뉴가 화면 높이에 맞춰 안에서 스크롤된다.
|
||||
- **글꼴**: 맑은 고딕(기본) · 굴림 · 돋움 · 바탕 | Arial · Verdana · Georgia · Times New Roman · Courier New. 목록의 이름은 그 글꼴로 보인다.
|
||||
- 본문 기본 글꼴은 맑은 고딕 스택 `'Malgun Gothic', '맑은 고딕', 'Apple SD Gothic Neo', sans-serif` 다 — 편집기 안 모양을 받는 사람이 보는 모양과 같게 한다.
|
||||
화면 UI 는 Pretendard 그대로다. 맥에서는 Apple SD 산돌고딕 Neo 로 보인다.
|
||||
- "맑은 고딕(기본)"을 고르면 글꼴 지정을 지운다.
|
||||
- **글자 크기(px)**: 12 · 13 · 14(기본) · 16 · 18 · 20 · 24 · 32. 제목 스타일(제목 1·2·3)은 두지 않는다. 고른 글자의 크기가 섞이면 "–".
|
||||
- **색 팔레트**(8색씩 · 견본 칸 40×40, 보이는 색 26 · 고른 색에 ✓ · 고른 색 이름을 글자로도 보인다):
|
||||
- 글자 색: 기본 #1F2733 · 회색 #667085 · 빨강 #B42318 · 주황 #B54708 · 초록 #067647 · 청록 #0E7C86 · 파랑 #175CD3 · 보라 #6941C6
|
||||
— 모두 흰 바탕 4.5:1 이상. "기본"은 글자 색을 지운다.
|
||||
- 배경 색: 없음 · 노랑 #FFF1A8 · 주황 #FDE4CC · 분홍 #FBDCE3 · 초록 #D9F2DF · 하늘 #D6E8FB · 보라 #E9E0FA · 회색 #E9EBEF
|
||||
— 본문 글자(#1F2733)가 10:1 이상 남는다. "없음"은 배경 색을 지운다.
|
||||
- **붙여 넣은 글 · 원문 인용의 서식**: 보낼 수 있는 형식(계약 2절 "서식 본문")만 받고 나머지는 버린다 — 색 이름(red) · Calibri 같은 서식은
|
||||
기본 모양으로 보인다. 편집기에 보이는 모양이 곧 받는 사람이 보는 모양이다 (2026-10-27 구현하며 정함).
|
||||
- **링크** 팝오버(폭 300): 주소 · 표시할 글자(비우면 주소). 새 링크는 [취소] [넣기], 이미 있는 링크는 [링크 빼기] … [취소] [적용].
|
||||
Enter = 적용, Esc = 닫고 본문으로. 주소는 http(s) · mailto 만 받는다.
|
||||
- **표 넣기**(더보기 ›): 8열 × 6행 격자에서 고른다("3행 × 4열"). 표 안의 행·열 추가·삭제는 다음 단계.
|
||||
- **메뉴·팝오버 공통**: 흰 바탕 · 테두리 #E6E8EC · 모서리 10 · 그림자 `--shadow-toast` · 툴바 아래 선 바로 밑에서 연다. Esc 로 닫는다.
|
||||
- **빈 본문**: 안내 문구 "내용을 입력하세요" · #667085(4.9:1). 커서는 문구 앞에 선다.
|
||||
- **문단**: 문단 사이 여백은 0 — Enter 한 번이 한 줄이다(지금 textarea 와 같다). 줄 간격은 1.75 이고, 보내는 본문도 같은 값이다
|
||||
(감싸는 div 의 `line-height` — 받는 사람이 편집기와 같은 모양으로 본다, 2026-10-27 구현하며 정함).
|
||||
여러 칸 띄어쓰기 · 줄 앞 공백도 받는 쪽에서 그대로 보이게 보낸다. 탭은 다음 8칸 자리까지의 공백이 된다(편집 영역의 탭 간격과 같다, 2026-10-27).
|
||||
|
||||
### 답장 · 전달의 원문 인용
|
||||
|
||||
- 원문은 인용 막대(왼쪽 2px #D0D5DD · 막대와 글 사이 14) 안에 둔다. 원문 글은 #4A5363, 내 글과 24 띄운다.
|
||||
- 머리는 답장 · 전달 모두 **"원본 메일"**(12.5px 굵게)이고, 그 아래에 항목 이름(#667085) · 값 표를 둔다.
|
||||
- 답장: 보낸 사람 · 날짜 · 제목 — 커서는 맨 위 첫 줄
|
||||
- 전달: 보낸 사람 · 날짜 · 받는 사람 · 참조 · 제목 — 커서는 받는 사람 칸
|
||||
- 막대는 회색이다 — 2px 브랜드색 선은 포커스 표시라 겹치지 않게 한다. 툴바의 "인용"도 같은 막대를 머리 없이 쓴다.
|
||||
- 초안이 한도(제목 255자 · 본문 텍스트 100,000자 · 서식 본문 500,000자 — 계약 2절)를 넘으면 인용을 줄이고 인용 끝에 "(원문이 길어 이하 생략)"을 둔다(2026-10-26 구현하며 정함 — 캔버스에는 그리지 않았다).
|
||||
- 처음 맞출 때 내 글 몫으로 한도의 5%를 남긴다. 보내기 직전에 다시 재서 넘으면 인용을 더 줄이고, 편집기에도 줄인 모양을 보인다(실행 취소로 되돌릴 수 있다).
|
||||
- 내 글만으로 넘으면 보내지 않는다 — 본문 아래(첨부 위)에 받는 사람 오류와 같은 빨간 띠로 알리고 본문에 초점을 준다.
|
||||
제목이 255자를 넘으면 제목 아래에 같은 띠를 둔다 (2026-10-27 구현하며 정함).
|
||||
|
||||
### 본문 이미지 → 첨부 파일
|
||||
|
||||
- 본문에는 이미지를 넣지 않는다(사용자 확정). 툴바에 이미지 버튼이 없다.
|
||||
- 본문에 붙여 넣거나(Ctrl+V) 끌어다 놓은 이미지는 첨부 파일로 올린다. 끌어다 놓은 다른 파일도 첨부로 올린다(쓰기 화면 어디에 놓아도 같다).
|
||||
한도는 첨부와 같다 — 넘치면 첨부 목록에 실패로 보인다(`States` 의 "첨부 업로드").
|
||||
- 클립보드에 **글이 함께 있으면 글을 붙여 넣는다** — 워드 · 엑셀에서 복사하면 고른 부분의 그림이 글과 함께 따라오기 때문이다.
|
||||
글 없이 파일만 있을 때 첨부로 돌린다 (2026-10-27 구현하며 정함 — 캔버스 시안은 그림이 있으면 늘 첨부로 돌린다).
|
||||
- 이름 없이 붙여 넣은 그림은 "붙여넣은 이미지 N.확장자"로 올린다. 원래 이름이 있는 파일은 그 이름 그대로다.
|
||||
- 끌어다 놓는 동안 본문 위에 점선 덮개(2px #0E7C86 점선 · 바탕 #F3F8F8)와 "놓으면 첨부 파일로 올립니다"를 보인다.
|
||||
쓰기 화면이 떠 있으면 파일은 창 어디(앱 레일 위 포함)에 놓아도 첨부로 받고, 덮개도 파일이 창 위에 있는 동안 보인다 —
|
||||
받지 않는 곳에 놓으면 브라우저가 그 파일을 열어 쓰던 메일을 잃기 때문이다 (2026-10-27 구현하며 정함).
|
||||
- 이미지를 첨부로 돌렸을 때만 성공 알림 "이미지는 본문 대신 첨부 파일로 올렸습니다."를 띄운다(성공 알림과 같은 모양 · 5초).
|
||||
|
||||
## 구현하며 정한 보완 (2026-10-26 — 캔버스에는 아직 없다)
|
||||
|
||||
- 쓰기 화면 첨부 안내문에 합계·개수 한도를 함께 적는다: "파일당 최대 20MB · 합계 25MB · 최대 20개 · 문서, 이미지, 압축 파일" (용량은 서버 값, 개수는 계약 상수).
|
||||
- 답장·전달 초안이 한도(제목 255자·본문 100,000자)를 넘으면 인용을 줄이고 끝에 "(원문이 길어 이하 생략)"을 둔다.
|
||||
- 찾지 못한 첨부(보관 시간이 지난 업로드·지워진 원본)는 실패로 표시하고, 전달 원본에는 "빼기"만 둔다(다시 올릴 수 없다).
|
||||
- 없는 메일함·메일(주소창에 남은 옛 id 등)에는 "다시 시도" 대신 "받은편지함으로"·"목록으로"를 둔다.
|
||||
"다시 시도"는 메일 서버 장애처럼 다시 해 보면 나아질 수 있는 오류에만 쓴다.
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
"Compose.dc.html": { "x": 3040, "y": 0, "w": 1440, "h": 900, "title": "메일 쓰기", "expand": "fill", "is_interactive": true },
|
||||
"States.dc.html": { "x": 0, "y": 1020, "w": 1440, "h": 1040, "title": "오류 · 빈 상태 · 피드백" },
|
||||
"MainList.dc.html": { "x": 1520, "y": 1020, "w": 1440, "h": 900, "title": "메일함 · 목록 보기", "expand": "fill", "is_interactive": true },
|
||||
"MainListRead.dc.html": { "x": 3040, "y": 1020, "w": 1440, "h": 900, "title": "목록 보기 · 메일 읽기", "expand": "fill", "is_interactive": true }
|
||||
"MainListRead.dc.html": { "x": 3040, "y": 1020, "w": 1440, "h": 900, "title": "목록 보기 · 메일 읽기", "expand": "fill", "is_interactive": true },
|
||||
"ComposeEditor.dc.html": { "x": 4560, "y": 0, "w": 1440, "h": 3576, "title": "메일 쓰기 · 편집기 상태" }
|
||||
},
|
||||
"order": ["Main.dc.html", "Login.dc.html", "Compose.dc.html", "States.dc.html", "MainList.dc.html", "MainListRead.dc.html"],
|
||||
"order": ["Main.dc.html", "Login.dc.html", "Compose.dc.html", "States.dc.html", "MainList.dc.html", "MainListRead.dc.html", "ComposeEditor.dc.html"],
|
||||
"notes": {
|
||||
"flow": { "x": 0, "y": -300, "text": "arasystem 웹메일 — 1단계 화면 (로그인 → 메일함 → 쓰기)", "kind": "title1", "maxW": 4480 }
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user