Skip to content

모바일 대화 화면 (메신저 · AI 어시스턴트) ​

직원 앱(모바일)의 메신저 전체화면과 AI 어시스턴트 페이지 모드를 한곳에 모았습니다. PC 의 채팅 위젯 · AI 어시스턴트 도크와 같은 컴포넌트·같은 템플릿을 쓰지만, 모바일에서만 켜지는 모양(캡슐형 입력줄 · 첫 화면 · 연락처 프로필)이 따로 있어서 이 페이지가 그 정본입니다.

Alpine 컴포넌트 · Mobile · 직원 앱 전용

Interactive playground ​

간호부 공지방
내일 교육 자료 공유드려요
확인했어요. 감사합니다!
3시까지 회의실로 와 주세요
① 메신저 채팅방 — 캡슐 + 첨부 「+」
AI 어시스턴트
AI
어떤 도움이 필요하세요?
② AI 어시스턴트 첫 화면 — 캡슐, 첨부 없음

두 입력칸을 눌러 보세요. ① 은 글을 치면 보내기 버튼이 나타나고, 바깥을 누르면 한 줄 말줄임으로 접힙니다. ② 는 비어 있는 채 누르면 예시 질문이, 「휴가」 처럼 치면 바로 갈 수 있는 화면이 입력줄 위에 뜹니다(「급여」 는 준비 중 메뉴).

데모의 한계

앱 헤더 · 화면 배치는 문서용 재현이고, 말풍선 · 입력줄 · 버튼은 실제 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 · 300ms cubic-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 → useHostHeadermode: 'page' → isPageMode
제목 · 뒤로가기앱 헤더앱 헤더(「AI 어시스턴트」), 「이전 대화」 는 헤더 오른쪽 아이콘
화면 바탕흰 면흰 면
하단 내비보임(분리형이면 섹션이 그 높이를 비움)숨음(.safe-bottom 을 화면이 짐)
입력줄캡슐 + 첨부 「+」 + 보내기캡슐 + 보내기(첨부 없음)
입력칸 안내 글「메시지를 입력하세요...」composerPlaceholder (직원 앱: 「예: 남은 휴가, 근무 기록, 외근 신청 방법」)
입력줄 위에 뜨는 것첨부 미리보기예시 질문 · 「바로 갈 수 있는 화면」 · 붙여 넣은 표 미리보기
모바일 전용 화면연락처 프로필첫 화면(업무 바로가기)
PC 에서의 모습채팅 위젯 — 캡슐 아님AI 어시스턴트 도크 — 캡슐 아님

캡슐형 입력줄 ​

모바일 두 화면이 같은 입력줄을 씁니다. PC 입력줄과 부품은 같고(.ds-composer* — 대화 UI), 모바일에서 클래스가 몇 개 더 붙습니다.

상태모습
비어 있음 · 포커스 없음한 줄 캡슐, 안내 글, 보내기 버튼 없음
비어 있음 · 포커스한 줄 캡슐(키보드 열림) — AI 는 이때 예시 질문이 위에 뜸
글 있음 · 포커스내용만큼 자람(최대 다섯 줄, 「크게」 네 줄), 보내기 버튼 보임
글 있음 · 포커스 없음한 줄로 접히고 친 글은 말줄임(…), 보내기 버튼 보임
글 없이 첨부만보내기 버튼 보임(활성)

위로 올려 보는 중에 새 메시지가 오면 캡슐 바로 위 가운데에 「새 메시지 n개」 알약이 뜹니다. 알약은 캡슐과 같은 묶음에 붙어 있어 키보드가 열리면 함께 올라가요. 규칙과 클래스는 PC 와 한 벌이라 대화 UI — 새 메시지 알약 이 정본입니다.

AI 어시스턴트 첫 화면 ​

대화가 비어 있을 때(getStartActions 를 준 마운트만) 뜹니다. 업무 바로가기가 주인공이고, 질문은 보조입니다 — 입력하지 않아도 시작할 수 있게.

  1. 인사 — BI 심볼(startBrandIcon) + 「AI」, 그 아래 질문(startHeading, h5 굵게). startHeading 이 없으면 이 줄을 그리지 않습니다.
  2. 업무 바로가기 — 한 줄에 하나씩, 글자만큼 폭. 누르면 AI 화면을 닫고 그 화면을 엽니다.
  3. 안내 문구 — 답변은 참고용 · 신청은 각 화면에서 · 불편 신고 · 메신저 안내(b5, 보조색).
  4. 예시 질문 — 입력칸을 누르면 입력줄 위에 둥근 제안(돋보기 + 문장)으로 뜹니다.
  5. 바로 갈 수 있는 화면 — 치는 동안 메뉴 이름 · 동의어로 맞춘 화면을 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) 그 직원 번호가 있을 때만 보입니다.

관련 ​

메신저 전체화면 ​

ts
Alpine.data("_messenger", () => messengerComponent({
  sectionName: "messenger",
  hostHeader: true,           // 앱 셸이 상단 앱바를 그린다 → 모바일 모양(캡슐 · 연락처 프로필 2depth)
}));

AI 어시스턴트 페이지 모드 ​

html
<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 템플릿이 이미 갖고 있으니 새로 짤 일은 드뭅니다. 새 모바일 대화 화면을 만들 때의 골격:

html
<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__btn40px(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바로가기 · 메뉴 결과를 눌렀을 때 — 호스트가 화면을 연다
examplePromptsstring[]예시 질문 — 입력칸을 눌렀고 비어 있을 때만 뜬다
getMenuCatalog() => AiMenuEntry[]치는 동안 AI 없이 맞춰 볼 메뉴. preparing: true 면 「준비 중」
composerPlaceholderstring입력칸 안내 글. 기본 「무엇이든 물어보세요」
startBrandIconstring첫 화면 맨 위 BI 심볼(레지스트리 이름)
startHeadingstring첫 화면 맨 위 질문. 없으면 인사 줄을 그리지 않음

단일 출처 ​

파트파일
스타일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 규칙에서 빠져 있습니다.