본문으로 건너뛰기

PlChatBubble

대화 속 메시지 하나입니다. 버블 주위의 모든 것은 선택이고, side가 정하는 것은 행이 어느 쪽으로 놓이는지와 시트의 어느 모서리가 짧게 잘리는지뿐입니다.

React
tsx
import { PlChatBubble } from 'plass-ui';

<PlChatBubble name="Ada Lovelace" time="09:12" avatar={<PlAvatar name="Ada Lovelace" />}>
  Have a look at the new fills.
</PlChatBubble>;

<PlChatBubble side="end" variant="solid" status="read">
  Already did.
</PlChatBubble>;

Props

Prop타입기본값설명
side공통'start' | 'end''start'누구의 메시지인지. them/me나 left/right가 아닌 이유는 대화가 언어가 흐르는 방향으로 흐르기 때문입니다. 행이 어느 쪽으로 놓이는지와 시트의 어느 모서리가 짧게 잘리는지를 정합니다
variant공통'solid' | 'glass' | 'ghost''glass'버블 표면의 재질. 버블은 색을 입는 대상 자체라 solid가 안을 채우고 글자가 --p-on-solid로 넘어갑니다. side와 묶여 있지 않은 것은 일부러입니다 — 어느 쪽을 채울지는 컴포넌트가 아니라 제품의 결정입니다
size공통'xs' | 'sm' | 'md' | 'lg' | 'xl''md'버블의 타입 스케일과 여백
color공통'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'의미론적 색 역할
density공통'default' | 'compact''default'버블 안쪽 여백만 바꿉니다
elevation공통0 | 1 | 2 | 30그림자 깊이. 메시지는 대화 위에 떠 있기보다 그 안에 놓입니다
nameReactNode보낸 사람. 버블 위에 놓입니다
timeReactNode보낸 시각. 이름 옆에 놓입니다
avatarReactNode보낸 사람의 사진 — 대화가 쓰는 크기의 PlAvatar. 없으면 버블이 행 전체를 씁니다
status'sending' | 'sent' | 'delivered' | 'read' | 'failed'메시지가 어디까지 갔는지. 버블 아래 표시로 그려집니다. 없으면 아무것도 그리지 않습니다 — 받은 메시지에는 보여 줄 전달 상태가 없습니다
statusLabelstring표시가 읽히는 말. 화면에는 그려지지 않습니다
typingbooleanfalse메시지 대신 점 세 개를 그립니다. children은 그대로 두므로, 메시지가 도착하면 같은 버블이 되돌아옵니다
typingLabelstring'Typing…'점이 읽히는 말. 화면에는 그려지지 않습니다
mediaReactNode사진, 영상, 지도 — 글 위에 가장자리까지 그려지고 버블의 모서리가 그것을 잘라 냅니다
previewPlChatBubbleLinkPreview메시지 속 링크를 글 아래 카드로 펼칩니다
actionsReactNode메시지 자신의 액션. 버블 옆에 놓이고, 행에 hover하거나 안의 무언가가 focus를 받기 전까지는 비켜서 있습니다
childrenReactNode메시지
Prop타입기본값설명
side공통PlChatBubbleSidePlChatBubbleSide.start누구의 메시지인지. them/me나 left/right가 아닌 이유는 대화가 언어가 흐르는 방향으로 흐르기 때문입니다. 행이 어느 쪽으로 놓이는지와 시트의 어느 모서리가 짧게 잘리는지를 정합니다
variant공통PlassVariantPlassVariant.glass버블 표면의 재질. 버블은 색을 입는 대상 자체라 solid가 안을 채우고 글자가 --p-on-solid로 넘어갑니다. side와 묶여 있지 않은 것은 일부러입니다 — 어느 쪽을 채울지는 컴포넌트가 아니라 제품의 결정입니다
size공통PlassSizePlassSize.md버블의 타입 스케일과 여백
color공통PlassColorPlassColor.primary의미론적 색 역할
density공통PlassDensityPlassDensity.standard버블 안쪽 여백만 바꿉니다
elevation공통int0그림자 깊이. 메시지는 대화 위에 떠 있기보다 그 안에 놓입니다
nameWidget?보낸 사람. 버블 위에 놓입니다
timeWidget?보낸 시각. 이름 옆에 놓입니다
avatarWidget?보낸 사람의 사진 — 대화가 쓰는 크기의 PlAvatar. 없으면 버블이 행 전체를 씁니다
statusPlChatBubbleStatus?메시지가 어디까지 갔는지. 버블 아래 표시로 그려집니다. 없으면 아무것도 그리지 않습니다 — 받은 메시지에는 보여 줄 전달 상태가 없습니다
statusLabelString?표시가 읽히는 말. 화면에는 그려지지 않습니다
typingboolfalse메시지 대신 점 세 개를 그립니다. child는 그대로 두므로, 메시지가 도착하면 같은 버블이 되돌아옵니다
typingLabelString'Typing…'점이 읽히는 말. 화면에는 그려지지 않습니다
mediaWidget?사진, 영상, 지도 — 글 위에 가장자리까지 그려지고 버블의 모서리가 그것을 잘라 냅니다
previewPlChatBubbleLinkPreview?메시지 속 링크를 글 아래 카드로 펼칩니다
actionsWidget?메시지 자신의 액션. 버블 옆에 있고, 그대로 있습니다 — 포인터가 확실히 있는 화면이라는 것이 없기 때문입니다
childWidget?메시지

네이티브 <div> 속성은 행에 그대로 전달됩니다. colortitle은 둘 다 여기서는 Plass의 prop이라 전달 대상에서 제외됩니다.

PlChatBubbleLinkPreview

Prop타입기본값설명
url * string카드가 가리키는 곳
titleReactNode페이지의 제목
descriptionReactNode요약. 두 줄로 잘립니다
imagestring카드 위쪽에 걸치는 공유 이미지
siteReactNode누가 낸 것인지 — 도메인, 사이트 이름
newTabbooleanfalse새 탭에서 엽니다. opener를 지키는 rel이 함께 붙습니다
Prop타입기본값설명
onPressedVoidCallback?카드를 눌렀을 때. url이 아닌 이유는 Flutter에 자기 내비게이션이 없기 때문입니다
titleWidget?페이지의 제목
descriptionWidget?요약. 두 줄로 잘립니다
imageImageProvider?카드 위쪽에 걸치는 공유 이미지. Flutter에서 모든 이미지가 갖는 모양입니다
siteWidget?누가 낸 것인지 — 도메인, 사이트 이름

라이브러리 전체에서 공유 축(side variant size color density elevation)이 뜻하는 바는 prop 규칙에 있습니다.

Examples

side

them/meleft/right가 아니라 startend입니다. 대화는 언어가 흐르는 방향으로 흐르고, 이 두 단어는 라이브러리의 다른 모든 자리에서 이미 그 뜻입니다.

말하는 쪽에 가까운 모서리가 짧게 잘립니다. 라이브러리가 가진 유일한 대화 어휘이고, 다른 곳에서 꼬리를 그려 하는 일을 대신합니다. 곧은 날로 잘렸어야 할 유리판에 삼각형을 매달지 않고서. 모든 크기에서 4px 고정인데, 반지름 사다리가 8px에서 16px까지밖에 가지 않아서 4px 차이는 누구도 의미로 읽지 않기 때문입니다.

React

variant

버블은 색을 입는 대상 자체입니다(남의 내용을 담기에 시트에 색이 들어가지 않는 PlCard와 다릅니다). 그래서 solid가 안을 채우고 글자는 그 계열의 잉크로 넘어갑니다. 내가 보낸 메시지의 세로줄이 한 줄씩이 아니라 한눈에 내 것으로 읽히게 하는 것이 그것입니다.

side와 묶여 있지 않은 것은 일부러입니다. 오른쪽 줄을 채우는 것은 관습이지 법이 아니고, 어느 쪽도 채우지 않는 대화도 아주 좋은 대화입니다.

React

status

다섯 중 둘만 색을 답니다. 도착한 것과 도착하지 못한 것. 그 사이의 셋은 그저 일이 흘러가는 보통의 모습이고, 모든 메시지가 색으로 표시된 대화는 색이 아무 뜻도 갖지 않게 된 대화입니다.

failed는 사다리의 다섯 번째 칸이 아닙니다. 가지 못한 메시지이고, 그래서 다른 계열로 그려지는 유일한 하나입니다.

React

typing

차례로 밝아지는 점 세 개입니다. 색만 바뀝니다. 점은 움직이지 않으므로, 누군가 입력 중인 버블이 다른 사람이 읽고 있는 대화 안에서 통통 튀지 않습니다.

childrenchild가 담고 있던 것은 그대로 두므로, 메시지가 도착하면 같은 버블이 그것으로 되돌아옵니다.

media와 preview

media는 글 위에 가장자리까지 그려지고, 버블 자신의 모서리가 그것을 잘라 냅니다. 버블의 여백이 시트가 아니라 각 구획에 놓여 있는 이유입니다.

링크 카드의 표면은 토큰이 아니라 currentColor에서 섞여 나옵니다. 버블에서 채워진 표면과 맨 표면 양쪽에서 모두 동작해야 하는 유일한 부분이기 때문입니다.

React

actions

손잡이는 행에 손이 닿기 전까지 메시지의 길에서 비켜서 있습니다. 그러지 않으면 읽고 있는 대화 한가운데에 놓이게 됩니다. 그리고 hover할 수 없는 포인터에는 그것을 드러낼 방법이 없으므로, 터치에서는 그냥 언제나 거기 있습니다.

React

size

React

Accessibility

  • 그려지는 것은 전달 표시뿐이고, 그 뒤의 말은 시각적으로 숨겨진 상자에 들어 있습니다. 이중 체크가 아무 말도 하지 않는 독자를 위해서입니다. statusLabel이 그 말을 바꿉니다.
  • 입력 중 점은 role="status"입니다. 그래서 누군가 쓰고 있다는 사실이 프레임마다가 아니라 한 번 읽힙니다.
  • 링크 카드는 진짜 <a>이고, newTab은 새 페이지가 window.opener로 되돌아오지 못하게 하는 rel을 함께 붙입니다.
  • media에는 자기 alt를 주세요. 컴포넌트는 그 사진이 무엇의 사진인지 알지 못합니다.
  • 버블은 자기 role을 더하지 않습니다. 대화는 목록이고, 그 목록은 페이지의 것입니다. 가상화된 대화도 여전히 목록일 수 있게 하는 것이 그것입니다.
  • 그려지는 것은 전달 표시뿐이고, 그 뒤의 말은 표시의 이름입니다. 이중 체크가 아무 말도 하지 않는 독자를 위해서입니다. statusLabel이 그 말을 바꿉니다.
  • 입력 중 점은 이름이 붙은 live region입니다. 그래서 누군가 쓰고 있다는 사실이 프레임마다가 아니라 한 번 읽힙니다. 점은 색만 바뀌고 움직이지 않으므로, 누군가 입력 중인 버블이 다른 사람이 읽고 있는 대화 안에서 통통 튀지 않습니다.
  • 링크 카드는 링크로 읽히고 키보드의 누름에도 답하며, 그 둘레에 focus ring이 그려집니다.
  • media에는 자기 이름을 주세요. 컴포넌트는 그 사진이 무엇의 사진인지 알지 못합니다.
  • 버블은 자기 role을 더하지 않습니다. 대화는 목록이고, 그 목록은 페이지의 것입니다. 게으르게 만들어지는 대화도 여전히 목록일 수 있게 하는 것이 그것입니다.

React 빌드와 다른 점

ReactFlutter이유
preview.urlnewTabpreview.onPressedFlutter에는 자기 내비게이션이 없으므로 링크가 어디로 가는지는 앱의 몫입니다.
srcpreview.imageImageProviderFlutter에서 모든 이미지가 갖는 모양입니다: 애셋, 파일, 네트워크 URL, 또는 그려진 것.
childrenchildFlutter의 이름입니다.
hover에서 나타나는 손잡이언제나 있는 손잡이여기에는 포인터가 확실히 있는 화면이라는 것이 없으니, 닿을 수 있는 쪽이 정직한 답입니다.
점의 role="status"이름이 붙은 live regionFlutter는 상태를 노드 자체에 적습니다.
className, style, 네이티브 속성전달할 클래스 목록도 style 속성도 없습니다.

Released under the MIT License