모바일 대화 화면 (메신저 · AI 어시스턴트)
직원 앱(모바일)의 메신저 전체화면과 AI 어시스턴트 페이지 모드를 한곳에 모았습니다. PC 의 채팅 위젯 · AI 어시스턴트 도크와 같은 컴포넌트·같은 템플릿을 쓰지만, 모바일에서만 켜지는 모양(캡슐형 입력줄 · 첫 화면 · 연락처 프로필)이 따로 있어서 이 페이지가 그 정본입니다.
Alpine 컴포넌트 · Mobile · 직원 앱 전용
Interactive playground
두 입력칸을 눌러 보세요. ① 은 글을 치면 보내기 버튼이 나타나고, 바깥을 누르면 한 줄 말줄임으로 접힙니다. ② 는 비어 있는 채 누르면 예시 질문이, 「휴가」 처럼 치면 바로 갈 수 있는 화면이 입력줄 위에 뜹니다(「급여」 는 준비 중 메뉴).
데모의 한계
앱 헤더 · 화면 배치는 문서용 재현이고, 말풍선 · 입력줄 · 버튼은 실제 design-system.css 클래스입니다. 하단 내비와의 여백, 화면 설정 배율(「크게」 네 줄)은 여기서 재현되지 않습니다.
규칙 (강제) · 코딩 에이전트용
모바일 대화 화면 강제 규칙. 상세는 아래 본문.
모바일인지는 옵션 하나가 정한다 — 화면 폭이 아니다
- 메신저는
messengerComponent({ hostHeader: true })(마크업에서는useHostHeader), AI 어시스턴트는aiAssistant({ mode: 'page' })(마크업에서는isPageMode)일 때만 모바일 모양이 켜진다. px 미디어쿼리로 모바일 모양을 켜지 말 것 — 같은 템플릿을 PC 채팅 위젯 · 관리자 AI 도크가 쓰므로, 폭으로 가르면 좁은 PC 창이 모바일 모양으로 바뀐다. - 두 옵션 모두 제목·뒤로가기를 앱 헤더(AppHeader)에 맡긴다는 뜻이다. 위젯 안쪽 제목줄은 그리지 않는다. 앱 헤더가 없는 화면(위젯)에 켜면 대화방에 갇힌다 → 메신저
hostHeader가 위험한 이유.
입력줄은 캡슐형(.ds-composer--capsule)이다
- 첨부(+) · 입력칸 · 보내기를 하나의 둥근 캡슐로 감싼다. 줄에
.ds-composer--capsule, 껍데기에.ds-composer-bar--capsule(윗선 없음 — 캡슐이 경계다). 선은 어디에도 없다 — 캡슐은 연한 면(neutral-75) 하나, 입력칸은ds-input-plain을 붙여 전역 입력칸의 흰 면·테두리·포커스 링을 받지 않는다. - 입력칸은
<textarea rows="1" class="ds-input--40 ds-input-plain ds-composer__field">— 폼 입력칸(ds-input--48)이 아니다. 캡슐 안 칸 40 + 위아래 4 = 캡슐 48 로 손가락 크기를 맞춘다. - 모서리는
--ds-composer-radius하나로 조절한다(기본 24 — 한 줄일 때 알약). 유틸(rounded-*)로 적지 말 것. - 입력칸은
.ds-composer__body안에 두고, 그 옆에.ds-composer__preview(친 글,aria-hidden)를 함께 둔다. 포커스가 빠지면 캡슐이 한 줄로 접히고 친 글은 미리보기 줄이 말줄임(…) 으로 보여 준다 — textarea 에는text-overflow가 먹지 않기 때문이다. 그동안 입력칸 글자는 투명. - 상태 클래스는 마크업이 붙인다 —
.is-focused(입력칸 포커스 = 키보드 열림) ·.has-text(친 글이 있음). 포커스면 여러 줄로 자란다 — 다섯 줄(직원 앱 화면 설정 「크게」 네 줄) 상한, 넘으면 칸 안에서 스크롤(2026-10-06 결정). 포커스를 얻는 순간 높이를 다시 재야 한다(@focus에서$nextTick으로 자동 높이 호출). - 보내기 버튼은 누를 수 있을 때만 보인다 — 아무것도 안 쳤을 때(비활성)는 버튼이 자리째 빠지고 입력칸이 그 폭을 쓴다(2026-10-06 결정). CSS 가
:disabled를 읽으므로 마크업은:disabled만 바르게 주면 된다 —x-show를 따로 달지 말 것. 글자 유무(.has-text)가 아니라 비활성으로 판정하는 이유는 글 없이 첨부만 있어도 보낼 수 있어서다(메신저 파일 · AI 이미지 — 그때 버튼은 활성이라 보인다). - 대화 목록의 위·아래 가장자리는 페이드다(
.ds-chat-scroll-fade, 2026-10-08) — 메신저 대화방 · AI 어시스턴트 둘 다. 스크롤하면 말풍선이 앱 헤더 밑 · 입력줄 위에서 칼같이 잘리지 않고 20px(--ds-chat-fade)에 걸쳐 흐려지며 사라진다. 클래스가 위·아래 패딩도 같은 값으로 잡아, 맨 위 · 맨 아래에 멈춰 있으면 말풍선이 흐려지지 않는다. 마스크(mask-image)라 바탕색과 상관없다 — 흰 그라데이션 띠를 덧그리지 말 것. PC 위젯 · 도크에는 붙이지 않는다. 직원 앱은 목록을 앱 헤더 뒤까지 올리므로(셸app-chat-under-header) 위쪽 페이드는 끄고(--ds-chat-fade-top: 0px) 헤더 높이를 위 패딩에 더한다(--ds-chat-inset-top) — 위쪽 흐림은 앱 헤더 유리층이 맡는다. 페이드는 입력줄 캡슐 윗선에서 바로 끝난다 — 캡슐(.ds-composer--capsule)의 위 여백은 0 이고(사이 흰 띠 없음), 캡슐 위에 얹히는 줄(답글 · 첨부 미리보기)이 아래 간격 8 을 직접 진다. - 대화방 검색칸은 모바일 채팅 전용 부품
.ds-chat-search-field다(2026-10-08) — 유리 알약(높이 44 — 앱 헤더의--ds-app-header-btn) 안에 돋보기(__icon) · 입력(__input) · 지우기 ⊗. 전역 입력칸(ds-input--*· 맨input)을 쓰지 말 것 — 흰 면 · 테두리 · 포커스 선이 붙는다(실제로 검은 포커스 테두리가 떴다). 입력에는ds-input-plain ds-chat-search-field__input을 함께 달아 전역 입력칸 규칙에서 빠지고, 포커스에도 선 · 링이 없다 — 포커스는 커서와 키보드가 보여 준다. - 메신저 대화방 검색은 대화 속에서 짚는다(2026-10-08 — 카카오톡 대화방 검색). 헤더 검색 아이콘을 누르면 헤더가 유리 검색칸 + 「취소」 가 되고(앱 헤더 검색 줄), 입력줄 자리에 검색 막대(
.ds-chat-search-bar— 입력줄 캡슐과 같은 자리 · 헤더 버튼과 같은 유리)가 뜬다: 왼쪽 「내가 보낸 메시지만」(ic-document-search— 문서 + 돋보기, 켜지면.is-active) · 가운데 「순번/건수」 · 오른쪽 ▲(더 예전) ▼(더 최근) 흰 원. 검색 키를 누르면 이 방 안만 찾고(conversationId, 최대 100건) 가장 최근 일치 메시지로 바로 가 잠깐 강조한다(.msg-anchor-flash). 결과 목록 패널은 직원 앱에서 쓰지 않는다(PC 위젯 전용). 대화는 검색 중에도 헤더 뒤로 지나간다. 막대 버튼은@mousedown.prevent— 눌러도 키보드가 내려가지 않는다. 날짜로 찾기는 아직 없다(서버 API 없음). - 휴대폰 키보드의 Enter 는 줄바꿈이고, 보내기는 화면의 보내기 버튼뿐이다(2026-10-13 사용자 결정 — 2026-10-08 의 「PC 와 같이 Enter 보내기」 를 되돌림). 판정은 PC 와 한 함수(
shouldSendOnEnter)이고coarsePointer(isCoarsePointer()=pointer: coarse)가 갈림길이다 — PC 는 Enter 보내기 · Shift+Enter 줄바꿈 그대로. 입력칸의enterkeyhint는 손가락 입력이면 「enter」, 아니면 「send」 로 바인딩한다(:enterkeyhint="composerCoarsePointer ? 'enter' : 'send'") — 고정enterkeyhint="send"를 다시 두지 말 것. 메신저 · AI 어시스턴트 입력줄 둘 다. - 캡슐 안 버튼은 40px(PC 입력줄 36px). 첨부(
--ghost)는 캡슐 안 흰 원, 보내기 아이콘은 흰색(.ds-composer__btn--send > .ds-ico— 전역 비활성 버튼 회색 강제를 아이콘 칸에서 피함). 보낼 것이 없으면 버튼째 숨는다(위 항목).
AI 어시스턴트 말풍선 · 꼬리표 · 메타 줄은 PC 와 한 벌이다
- 직원 앱 AI 어시스턴트(페이지 모드)는 PC 도크와 같은
ai-assistant-conversation.html을 그린다. 그래서 아래는 AI 어시스턴트 문서가 정본이고 직원 앱에도 똑같이 적용된다(2026-10-08): 꼬리표 버튼은 아이콘 버튼ds-btn--icon --muted --xs(복사 · 문제 신고ic-megaphone) · 토큰 사용량 · 👍/👎 · 오류 코드 · 답변 소요 시간은 숨김(메타 줄은 시각만) · 답변 대기 상태 줄(「질문을 이해하고 계획하는 중」 + 경과 초)은 말풍선 배경 없이 글자만 · 보낸 말풍선을 감싸는 상자는w-full(대화 UI 규칙). 직원 앱에서만 따로 덮지 말 것. - 다른 점은 이전 대화뿐이다 — 직원 앱은 화면이 좁아 본문 옆 사이드바 대신 오른쪽 서랍(
.ds-ai-drawer)을 쓴다. 처음 들어오면 PC 와 같이 새 대화(첫 화면)로 시작한다.
AI 어시스턴트 이전 대화 서랍(2026-10-08)
- 오른쪽에서 나온다. Claude · ChatGPT 모바일 앱의 사이드바를 따르되 방향만 거울로 뒤집었다 — 앱 헤더 왼쪽이 「뒤로(<)」 자리이고, 왼쪽 가장자리 스와이프는 iOS 뒤로 가기 몫이라서다. 서랍을 왼쪽으로 옮기지 말 것.
- 여는 길 둘 — 앱 헤더 오른쪽 아이콘(
ic-menu, 라벨 「이전 대화」 →app-ai-history→openHistory()) · 대화 화면을 왼쪽으로 밀기(서랍이 손가락을 따라 나온다). 표 · 코드 블록처럼 가로로 스크롤되는 곳에서 시작한 밀기는 그 스크롤에 양보한다. - 서랍과 딤은 앱 헤더 위까지 덮는다(2026-10-12) — 마크업을 body 로 옮겨(
x-teleport) 화면 전체 층.ds-ai-drawer-layer(헤더--ds-z-nav보다 한 층 위) 안에 그린다. 대화 화면을 감싼 스크롤 영역이 겹침 층을 만들어, 제자리에서는 z-index 를 올려도 헤더 아래에 갇혔다(iOS 실기기). 서랍 안쪽은 상태 표시줄 높이만큼 내려 시작한다. 예전(10-08)엔 헤더 아래만 덮어 「<」 · 목록 아이콘이 보였다. - 「새 대화」 는 서랍 바닥에 붙는다(2026-10-12) —
.ds-ai-drawer__foot, 버튼ds-btn--solid --muted --ml·ds-r-16(40 · 모서리 16). 목록만 스크롤되고 버튼은 늘 보인다. 홈 인디케이터 여백은 이 줄이 진다. 예전엔 맨 위__head에 md(32) 였다. - 닫는 길 — 딤 탭(헤더 자리 포함) · 서랍을 오른쪽으로 밀기 · 대화 고르기 · 「새 대화」 · 기기 뒤로 가기(서랍만 닫고 AI 화면은 남는다 —
$store.aiApp.historyOpen). 앱 헤더 「<」 는 서랍이 열린 동안 딤 아래에 있다. AI 화면을 떠나면 서랍도 닫힌다. - 손을 떼면 빠르게 튕긴 방향(0.5px/ms 이상)을 먼저 따르고, 아니면 절반을 넘었는지로 열림/닫힘을 정한다(
shouldDrawerStayOpen). 끄는 동안에는 전환이 꺼지고 손가락 위치를 그대로 따른다. - 덮는 범위는 패널 안(앱 헤더 아래)이다 — 앱 헤더의 「<」 와 이전 대화 아이콘이 계속 보이고 눌린다. 그래서
.ds-chat-panel--page가position: relative다. - 폭
min(85%, 320px)· 뒤 딤--ds-dim-40· 300mscubic-bezier(0.32, 0.72, 0, 1)(엣지 스와이프 뒤로 가기와 같은 곡선) ·prefers-reduced-motion이면 전환 없음. 맨 위 「새 대화」(ds-btn--line --muted --md) → 「최근 대화」 라벨(b5) → 행(44px · b4 · 한 줄 말줄임 · 날짜 없음, 지금 대화는.is-active). - 위치는 변수 두 개(
--ds-ai-drawer-offset·--ds-ai-drawer-progress)만 읽는다 — 끄는 동안 마크업:style이 이 둘을 덮는다.transform·opacity를 마크업에 직접 쓰지 말 것. - 서랍 · 딤의
touchstart는.stop이다 — 안 그러면 문서에 걸린 iOS 엣지 스와이프가 같은 손가락으로 AI 화면째 밀어 버린다.
AI 어시스턴트 첫 화면
- 업무 바로가기는 AI 를 거치지 않는다 — 누르면
onStartAction(id)로 호스트 앱이 화면을 연다. AI 가 멈춰도 쓸 수 있어야 해서다. 버튼은ds-btn ds-btn--solid ds-btn--lightor ds-btn--md ds-r-12 ds-chat-start-action(글자만큼 폭), 한 줄에 하나씩 왼쪽 정렬. - 맨 위 BI 심볼은 호스트가 준다(
startBrandIcon) — 공용 템플릿에 브랜드를 하드코딩하지 말 것. 직원 앱은logo-hereby-works(패밀리). - 예시 질문은 입력칸을 눌렀고 아직 아무것도 안 쳤을 때만 입력줄 위에 뜬다. 누르면 그 문장을 보낸다. 누르는 순간 입력칸 포커스가 빠져 목록이 먼저 사라지지 않도록
@mousedown.prevent를 둔다. - 「바로 갈 수 있는 화면」 은 입력줄 위에 떠서 뒤 대화와 겹치는 팝오버(
shadow-popover, 구분선 없음)다. 줄마다ds-btn ds-btn--line ds-btn--muted ds-btn--ml ds-r-12 ds-chat-menu-action(팝오버 흰 면 위라 테두리형 — 첫 화면 업무 바로가기의 solid · lightor 와 다르다), 아직 없는 메뉴는:disabled+ 「준비 중」 라벨(AiMenuEntry.preparing)이고 눌러도 열리지 않는다. - 입력줄 위에 얹히는 것(예시 질문 · 팝오버 · 첨부 미리보기 · 사용량 경고)은
.ds-composer-bar안,.ds-composer밖에 둔다.
화면 바탕 · 하단 내비
- 두 화면 모두 흰 면이다. 메신저는 1depth 라 하단 내비가 보이고, 분리형 하단 내비의 그라데이션 끝 색을 흰색으로 넘긴다(
--ds-bottom-nav-surface) — 안 넘기면 셸 회색 띠가 생긴다. 메신저 섹션은 안쪽 목록이 따로 스크롤하므로 하단 내비 높이만큼 섹션에 여백을 비운다 → 하단 내비게이션 분리형. - AI 어시스턴트는 2depth(하단 내비 숨음)라 홈 인디케이터 여백(
.safe-bottom)을 화면이 직접 지고, 셸의 스크롤 끝 여백은 받지 않는다(받으면 입력줄 아래 회색 띠). 직원 앱은 메신저 대화방 · AI 어시스턴트 입력줄의 이 여백을 하단 내비 캡슐과 같은 바닥 여백--app-nav-bottom-gap(iOS 는 홈 인디케이터 바로 위 22, 앱main.css)으로 줄인다 — 입력줄 캡슐 margin 8 + 패딩 = 그 값이고, 키보드가 열리면 safe-area 가 0 이라 예전처럼 8 만 남는다(2026-10-07).
글자
- 직원 앱 최소 글자 13px(b5) — 첫 화면 · 연락처 프로필의 새 글자는 b5 이상. 단 메신저 템플릿은 PC 채팅 위젯과 한 벌이라 그 안의 12px 은 아직 남아 있다(앱에서 덮지 않음).
- 다크 모드(2026-10-13) — 방 안 검색 줄의 이동 버튼
.ds-chat-search-bar__nav면은bg-container, 검색 줄 · 앱 헤더 유리는--color-bg-glass(다크 neutral-800)를 섞는다. 직원 앱 대화방 바탕 자체는messenger-content.html의bg-bg-container(10/19, 전bg-white). 이 페이지에는 Playground 가 없어 다크 미리보기가 없다 — 직원 앱 「화면 설정 → 다크」로 확인한다.
두 화면
| 메신저 전체화면 | AI 어시스턴트 페이지 모드 | |
|---|---|---|
| 들어가는 길 | 하단 탭 「메신저」 (1depth) | 하단 내비 오른쪽 AI 원 버튼 → 2depth(더보기 목록에는 없음) |
| 켜는 옵션 | hostHeader: true → useHostHeader | mode: 'page' → isPageMode |
| 제목 · 뒤로가기 | 앱 헤더 | 앱 헤더(「AI 어시스턴트」), 「이전 대화」 는 헤더 오른쪽 아이콘 |
| 화면 바탕 | 흰 면 | 흰 면 |
| 하단 내비 | 보임(분리형이면 섹션이 그 높이를 비움) | 숨음(.safe-bottom 을 화면이 짐) |
| 입력줄 | 캡슐 + 첨부 「+」 + 보내기 | 캡슐 + 보내기(첨부 없음) |
| 입력칸 안내 글 | 「메시지를 입력하세요...」 | composerPlaceholder (직원 앱: 「예: 남은 휴가, 근무 기록, 외근 신청 방법」) |
| 입력줄 위에 뜨는 것 | 첨부 미리보기 | 예시 질문 · 「바로 갈 수 있는 화면」 · 붙여 넣은 표 미리보기 |
| 모바일 전용 화면 | 연락처 프로필 | 첫 화면(업무 바로가기) |
| PC 에서의 모습 | 채팅 위젯 — 캡슐 아님 | AI 어시스턴트 도크 — 캡슐 아님 |
캡슐형 입력줄
모바일 두 화면이 같은 입력줄을 씁니다. PC 입력줄과 부품은 같고(.ds-composer* — 대화 UI), 모바일에서 클래스가 몇 개 더 붙습니다.
| 상태 | 모습 |
|---|---|
| 비어 있음 · 포커스 없음 | 한 줄 캡슐, 안내 글, 보내기 버튼 없음 |
| 비어 있음 · 포커스 | 한 줄 캡슐(키보드 열림) — AI 는 이때 예시 질문이 위에 뜸 |
| 글 있음 · 포커스 | 내용만큼 자람(최대 다섯 줄, 「크게」 네 줄), 보내기 버튼 보임 |
| 글 있음 · 포커스 없음 | 한 줄로 접히고 친 글은 말줄임(…), 보내기 버튼 보임 |
| 글 없이 첨부만 | 보내기 버튼 보임(활성) |
위로 올려 보는 중에 새 메시지가 오면 캡슐 바로 위 가운데에 「새 메시지 n개」 알약이 뜹니다. 알약은 캡슐과 같은 묶음에 붙어 있어 키보드가 열리면 함께 올라가요. 규칙과 클래스는 PC 와 한 벌이라 대화 UI — 새 메시지 알약 이 정본입니다.
AI 어시스턴트 첫 화면
대화가 비어 있을 때(getStartActions 를 준 마운트만) 뜹니다. 업무 바로가기가 주인공이고, 질문은 보조입니다 — 입력하지 않아도 시작할 수 있게.
- 인사 — BI 심볼(
startBrandIcon) + 「AI」, 그 아래 질문(startHeading, h5 굵게).startHeading이 없으면 이 줄을 그리지 않습니다. - 업무 바로가기 — 한 줄에 하나씩, 글자만큼 폭. 누르면 AI 화면을 닫고 그 화면을 엽니다.
- 안내 문구 — 답변은 참고용 · 신청은 각 화면에서 · 불편 신고 · 메신저 안내(b5, 보조색).
- 예시 질문 — 입력칸을 누르면 입력줄 위에 둥근 제안(돋보기 + 문장)으로 뜹니다.
- 바로 갈 수 있는 화면 — 치는 동안 메뉴 이름 · 동의어로 맞춘 화면을 AI 없이 보여 줍니다(
getMenuCatalog). 「검색」 과 「질문」 을 고르게 하지 않고 한 입력줄에서 둘 다 받습니다 — 화면이 맞으면 누르고, 아니면 그대로 보내 AI 에게 묻습니다. 실패한 답변 아래에도 같은 바로가기가 다시 뜹니다.
메신저 연락처 프로필
연락처를 누르면 1:1 채팅 전에 이 화면이 먼저 열립니다(직원 앱에서는 2depth — 헤더 뒤로가기 = 연락처 목록).
- 사진(80px 원) · 이름(h5) · 대표 소속, 그 아래 정보 줄(소속 · 역할 · 직무 · 직군 · 직위 · 이메일). 빈 칸은 줄째 빠집니다.
- 버튼: 「1:1 채팅」(
ds-btn--solid ds-btn--primary ds-btn--lg ds-r-16) · 「전화하기」(ds-btn--line ds-btn--dark ds-btn--lg ds-r-16). 전화하기는 병원이 전화번호를 공개하고(관리자 「병원 설정 → 메신저 연락처 공개」,contactSharing.phone) 그 직원 번호가 있을 때만 보입니다.
관련
- 대화 UI — 패널 · 말풍선 · 입력줄 부품(PC · 모바일 공통)
- 메신저 — 두 모드(전체화면 / 위젯) · 화면 · API
- AI 어시스턴트 — PC 도크 · 플로팅
- 하단 내비게이션 — AI 원 버튼(실행 버튼) · 분리형 여백
- 폼 컨트롤 → 모바일 텍스트 필드 — 폼 입력칸과 대화 입력줄의 구분
메신저 전체화면
Alpine.data("_messenger", () => messengerComponent({
sectionName: "messenger",
hostHeader: true, // 앱 셸이 상단 앱바를 그린다 → 모바일 모양(캡슐 · 연락처 프로필 2depth)
}));AI 어시스턴트 페이지 모드
<div x-show="showAiAssistant" class="h-full min-h-0"
x-data="aiAssistant({
app: 'employee-app',
mode: 'page',
permission: 'aiApp:execute',
requireModule: 'employeeApp',
getStartActions: () => aiHelpStartActions(),
examplePrompts: aiHelpExamples,
getMenuCatalog: () => aiHelpMenuCatalog(),
onStartAction: (id) => runAiHelpAction(id),
composerPlaceholder: aiHelpPlaceholder,
startBrandIcon: 'logo-hereby-works',
startHeading: '어떤 도움이 필요하세요?',
})"
x-effect="if (showAiAssistant) openPage()">
<!-- include "../../packages/components/html/ai-assistant-page.html" -->
</div>ai-assistant-page.html 이 .ds-chat-panel--page(테두리 · 그림자 · 고정 크기 없이 부모 높이를 채움) + .safe-bottom 으로 감싸고, 안에서 ai-assistant-conversation.html 을 include 합니다.
캡슐형 입력줄 마크업
메신저 · AI 템플릿이 이미 갖고 있으니 새로 짤 일은 드뭅니다. 새 모바일 대화 화면을 만들 때의 골격:
<div class="ds-composer-bar ds-composer-bar--capsule">
<!-- (선택) 입력줄 위에 얹히는 것 — 껍데기 안, 줄 밖 -->
<div class="ds-composer ds-composer--multiline ds-composer--capsule"
x-data="{ focus: false }" :class="{ 'is-focused': focus, 'has-text': text.trim() !== '' }">
<!-- (선택) 첨부 — AI 는 없음 -->
<button type="button" class="ds-composer__btn ds-composer__btn--ghost" aria-label="파일 첨부" title="파일 첨부" data-ds-tip="top">
<span class="ds-ico w-5 h-5" aria-hidden="true" x-html="$icon('ic-plus')"></span>
</button>
<div class="ds-composer__body">
<textarea rows="1" x-model="text" class="ds-input--40 ds-input-plain ds-composer__field"
@focus="focus = true; $nextTick(() => autosize($el))" @blur="focus = false"></textarea>
<div class="ds-composer__preview" aria-hidden="true" x-text="text"></div>
</div>
<!-- :disabled 만 주면 비어 있을 때 CSS 가 숨긴다 — x-show 를 달지 말 것 -->
<button type="button" class="ds-composer__btn ds-composer__btn--send" :disabled="!text.trim()"
aria-label="보내기" title="보내기" data-ds-tip="top">
<span class="ds-ico w-4 h-4" aria-hidden="true" x-html="$icon('ic-send')"></span>
</button>
</div>
</div>캡슐형 입력줄 클래스
| 클래스 | 무엇 |
|---|---|
.ds-composer--capsule | 캡슐형 줄 — 연한 면(neutral-75) 하나에 버튼 · 입력칸을 감싼다. 안쪽 여백 4 · 간격 4 · 바깥 여백 8/12. 모서리 --ds-composer-radius(기본 24) |
.ds-composer-bar--capsule | 캡슐형 껍데기 — 윗선 없음 |
.ds-composer__body | 입력칸 + 미리보기 줄을 겹쳐 두는 칸 |
.ds-composer__preview | 포커스가 빠졌을 때 친 글을 한 줄 말줄임으로 보여 주는 줄(aria-hidden) |
.is-focused · .has-text | 줄의 상태 — 마크업이 붙인다 |
.ds-composer--capsule .ds-composer__btn | 40px(PC 36px) |
.ds-composer--capsule .ds-composer__btn--ghost | 첨부 — 캡슐 안 흰 원 |
.ds-composer--capsule .ds-composer__btn--send:disabled | 숨김(display: none) |
AI 첫 화면 클래스
| 클래스 | 무엇 |
|---|---|
.ds-chat-start-action | 업무 바로가기 버튼(ds-btn ds-btn--solid ds-btn--lightor ds-btn--md ds-r-12 와 함께) — .ds-btn 최소 폭(80)을 풀어 글자만큼 |
.ds-chat-menu-action | 「바로 갈 수 있는 화면」 메뉴 버튼(ds-btn ds-btn--line ds-btn--muted ds-btn--ml ds-r-12 와 함께) — 팝오버 폭을 채우고 이름 왼쪽 · 화살표/「준비 중」 오른쪽 |
.ds-chat-panel--page | 페이지 모드 패널 — 고정 크기 · 테두리 · 그림자 없이 부모 높이를 채움 |
AI 어시스턴트 페이지 모드 옵션
| 옵션 | 타입 | 설명 |
|---|---|---|
mode | 'fab' | 'page' | 'page' 면 이 페이지의 모바일 모양 |
getStartActions | () => AiStartAction[] | 첫 화면 업무 바로가기. 비거나 없으면 예전 빈 화면 안내(emptyStateText) |
onStartAction | (id: string) => void | 바로가기 · 메뉴 결과를 눌렀을 때 — 호스트가 화면을 연다 |
examplePrompts | string[] | 예시 질문 — 입력칸을 눌렀고 비어 있을 때만 뜬다 |
getMenuCatalog | () => AiMenuEntry[] | 치는 동안 AI 없이 맞춰 볼 메뉴. preparing: true 면 「준비 중」 |
composerPlaceholder | string | 입력칸 안내 글. 기본 「무엇이든 물어보세요」 |
startBrandIcon | string | 첫 화면 맨 위 BI 심볼(레지스트리 이름) |
startHeading | string | 첫 화면 맨 위 질문. 없으면 인사 줄을 그리지 않음 |
단일 출처
| 파트 | 파일 |
|---|---|
| 스타일 | packages/static/styles/design-system.css (.ds-composer--capsule · .ds-chat-start-action · .ds-chat-menu-action · .ds-chat-panel--page) |
| 메신저 템플릿 | packages/components/html/messenger-content.html (useHostHeader 갈래) |
| AI 템플릿 | ai-assistant-page.html → ai-assistant-conversation.html (isPageMode 갈래) |
| 직원 앱 마운트 | apps/employee-app/src/views/sections/more.html (AI) · views/app-shell.html (메신저) · 첫 화면 목록 src/utils/ai-help.ts |
| 「크게」 네 줄 | apps/employee-app/src/styles/main.css |
변경 이력
- 2026-10-13 — 휴대폰 키보드의 Enter 를 다시 줄바꿈으로(보내기는 버튼뿐).
shouldSendOnEnter의coarsePointer·enterkeyhint바인딩 - 2026-10-12 — 캡슐 위 「새 메시지 n개」 알약 안내 추가(정본은 대화 UI)
- 2026-10-08 — AI 말풍선 · 꼬리표 · 메타 줄 · 대기 상태 줄이 PC 와 한 벌임을 규칙에 명시(꼬리표 아이콘 버튼 xs · 토큰/👍👎/오류 코드/소요 시간 숨김 · 대기 상태는 글자만 · 보낸 말풍선 폭 수정)
- 2026-10-06 — 페이지 신설. 대화 UI 페이지에 있던 캡슐형 입력줄 규칙 · AI 첫 화면 클래스를 이 페이지로 옮기고(대화 UI 에는 링크만), 메신저 · AI 어시스턴트 문서의 모바일 내용을 여기로 모았습니다. 캡슐형 입력줄 보내기 버튼 비활성 숨김 포함 → 변경 이력
남은 것
- 예시 질문 칩은 DS 클래스가 아닙니다 —
rounded-full border bg-white min-h-11 px-4유틸 조합(div role="button")입니다. 두 번째 사용처가 생기면 DS 축으로 뺄 후보입니다. - 메신저 템플릿 안 12px 글자 — PC 위젯과 한 벌이라 직원 앱 최소 13px 규칙에서 빠져 있습니다.