본문으로 건너뛰기

PlHoverCard

링크 뒤에 무엇이 있는지 미리 보여 주는 카드입니다. 포인터가 그 위에 머물면 열립니다. 지나가는 길의 모든 링크에서 튀어나오지 않을 만큼 늦게 열리고, 손이 닿을 수 있을 만큼 천천히 닫힙니다.

React
tsx
import { PlHoverCard, PlTextLink } from 'plass-ui';

<PlHoverCard
  title="Ada Lovelace"
  description="Mathematician, 1815–1852"
  trigger={<PlTextLink href="/ada">Ada Lovelace</PlTextLink>}
>
  Wrote the first algorithm intended to be carried out by a machine.
</PlHoverCard>;
dart
import 'package:plass_ui/plass_ui.dart';

PlHoverCard(
  title: const Text('Ada Lovelace'),
  description: const Text('Mathematician, 1815–1852'),
  trigger: PlTextLink(onPressed: open, child: const Text('Ada Lovelace')),
  child: const Text('Wrote the first algorithm intended to be carried out by a machine.'),
);

Props

Prop타입기본값설명
trigger * ReactElement카드가 미리 보여 주는 대상. 보통 링크이고, 감싸지 않고 그대로 렌더링됩니다
title · descriptionReactNode제목과 그 아래 한 줄
childrenReactNode본문
side'top' | 'right' | 'bottom' | 'left''bottom'트리거의 어느 모서리에 나타날지. 자리가 없으면 반대쪽으로 뒤집힙니다
align'start' | 'center' | 'end''center'그 모서리를 따라 어디에 놓일지
sideOffset · alignOffsetnumber8 · 0트리거에서 떨어진 거리와 모서리를 따라 밀린 거리, 픽셀
delaynumber600열리기까지 포인터가 머물러야 하는 시간(ms). 지나가는 길의 모든 링크에서 열리지 않도록 깁니다
closeDelaynumber300포인터가 떠난 뒤 기다리는 시간(ms). 0일 수 없습니다 — 트리거와 카드 사이의 틈에는 포인터가 없습니다
arrowbooleanfalse트리거를 가리키는 작은 쐐기를 그립니다
open · defaultOpen · onOpenChangeboolean · boolean · (open) => void바깥에서 여닫기. 주지 않으면 포인터와 키보드에 맡깁니다
widthnumber | stringsize가 정하는 최대 너비를 덮어씁니다
size공통'xs' | 'sm' | 'md' | 'lg' | 'xl''md'시트의 타입 스케일과 radius와 패딩
color공통'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'안쪽이 쓰는 색 역할
density공통'default' | 'compact''default'시트가 내용을 얼마나 촘촘히 담을지
Prop타입기본값설명
trigger * Widget카드가 미리 보여 주는 대상. 보통 링크이고, 감싸지 않고 그대로 렌더링됩니다
title · descriptionWidget?제목과 그 아래 한 줄
childWidget?본문
sidePlassSidePlassSide.bottom트리거의 어느 모서리에 나타날지. 자리가 없으면 반대쪽으로 뒤집힙니다
alignPlassAlignPlassAlign.center그 모서리를 따라 어디에 놓일지
offsetdouble8트리거에서 떨어진 거리와 모서리를 따라 밀린 거리, 픽셀
delayDuration600ms열리기까지 포인터가 머물러야 하는 시간(ms). 지나가는 길의 모든 링크에서 열리지 않도록 깁니다
closeDelayDuration300ms포인터가 떠난 뒤 기다리는 시간(ms). 0일 수 없습니다 — 트리거와 카드 사이의 틈에는 포인터가 없습니다
arrowboolfalse트리거를 가리키는 작은 쐐기를 그립니다
open · onOpenChangedbool? · ValueChanged<bool>?바깥에서 여닫기. 주지 않으면 포인터와 키보드에 맡깁니다
disabledboolfalse트리거를 비활성화하지 않으면서 카드만 열리지 않게 합니다
widthdouble?size가 정하는 최대 너비를 덮어씁니다
size공통PlassSizePlassSize.md시트의 타입 스케일과 radius와 패딩
color공통PlassColorPlassColor.primary안쪽이 쓰는 색 역할
density공통PlassDensityPlassDensity.standard시트가 내용을 얼마나 촘촘히 담을지

라이브러리 전체에서 공유 축이 무엇을 뜻하는지는 prop 규약에 있습니다.

Hover card, 툴팁, popover 중 고르기

셋이 있고, 구분하는 것은 무엇이 여는가와 열린 뒤에 무엇을 할 수 있는가입니다. 생김새가 아닙니다. 셋 다 같은 시트입니다.

여는 것열린 뒤
PlTooltip위에 머무르기한 구절뿐이고 안의 어떤 것에도 닿을 수 없습니다
PlHoverCard위에 머무르기포인터가 안으로 들어갈 수 있고, 제목·그림·수치가 들어갑니다
PlPopover누르기닫을 때까지 남고, 입력도 받습니다

여기에만 있는 것은 없어야 합니다

이 컴포넌트가 맞는 선택인지를 정하는 규칙입니다.

hover로 열리는 카드는 손가락으로는 열리지 않습니다. 페이지의 다른 어디에도 없는 링크나 버튼이나 사실은, 터치로 읽는 사람 모두가 놓치는 링크·버튼·사실입니다. 그래서 안에 있는 것은 전부 이미 닿을 수 있는 무언가의 미리 보기입니다. 트리거가 가는 페이지, 자기 화면이 붙은 프로필, 아래 표에 다시 나오는 수치.

그래서 애초에 안전하고, 그래서 닫기 버튼도 포커스 가둠도 스크롤 잠금도 필요 없습니다. 끝까지 보지 못해도 잃는 것이 없습니다.

지연

delay600ms이고 일부러 깁니다. 포인터가 링크를 스치는 순간 열리는 카드는 다른 곳으로 가는 길에 지나치는 모든 링크에서 열립니다. 그러면 글이 있는 페이지가 움찔거리는 페이지가 됩니다.

closeDelay300ms이고 0일 수 없습니다. 트리거와 카드 사이의 틈에는 포인터가 없으므로, 트리거를 벗어나는 순간 닫히는 카드에는 영영 닿을 수 없습니다. 그리고 거기에 닿을 수 있다는 것이 tooltip과의 차이 전부입니다.

React

링크가 전부 미리 보기인 페이지(사람 목록, 이슈 목록) 에서만 delay를 줄이고, 나머지에서는 그대로 두십시오.

Examples

사람

흔한 경우이고, 이 컴포넌트가 그려진 모양입니다.

tsx
<PlHoverCard
  title="Ada Lovelace"
  description="Mathematician"
  trigger={<PlTextLink href="/people/ada">Ada Lovelace</PlTextLink>}
>
  <div className="flex items-center gap-3">
    <PlAvatar name="Ada Lovelace" />
    <p>Wrote the first algorithm intended for a machine.</p>
  </div>
</PlHoverCard>

링크 아래가 아닌 자리

side, align과 두 offset은 popover가 받는 것과 같은 넷이고, 자리가 없으면 반대쪽으로 뒤집힙니다.

tsx
<PlHoverCard side="right" align="start" arrow trigger={…}>…</PlHoverCard>

Notes

  • 트리거는 감싸는 것이 아니라 그대로 렌더링됩니다. 링크는 링크로 남아 href와 스타일과 tab 순서를 유지하고, 카드는 레이아웃에 상자를 더하지 않습니다.
  • 시트는 popover가 그리는 것과 같은 서리 낀 패널이고, size 단계마다 한 칸씩 넓습니다. popover는 컨트롤 옆의 세부 사항이고, 힌트 폭으로 눌린 미리 보기는 아무도 읽지 않습니다.
  • arrow는 popover와 마찬가지로 기본이 꺼짐입니다. 시트는 흐려진 배경 위의 반투명이고, 자기 상자 밖으로 튀어나온 쐐기는 그 배경을 함께 가져가지 못합니다.
  • Base UI의 PreviewCard가 앵커링, 창 가장자리에서의 뒤집기, 두 지연, 닫기를 가집니다.
  • 포인터를 트리거와 카드 양쪽에서 따라가고, 플래그가 하나가 아니라 둘입니다. 그래서 둘 사이의 틈을 건널 수 있습니다.
  • 위에 Overlay가 필요합니다. navigator가 있는 WidgetsAppMaterialApp 둘 다 제공합니다.

Accessibility

  • hover뿐 아니라 키보드 포커스에서도 열립니다. 링크가 이어진 문단을 tab으로 지나가는 사람도 포인터와 같은 미리 보기를 받습니다. hover만 받는 카드가 잃는 절반이고, 여기서는 공짜입니다.
  • Escape로 닫힙니다.
  • dialog가 아니고 포커스를 가져가지 않습니다. 안에 있는 것은 포인터로 닿을 수 있고, 위의 규칙대로 포인터 없이도 닿을 수 있어야 합니다.
  • 트리거는 원래 가지고 있던 role을 그대로 유지합니다. 카드를 여는 링크도 여전히 링크이고, 말한 곳으로 갑니다.

Released under the MIT License