불확실성과 연결 오류를 노출하는 상태 대시보드 설계

작성자

카테고리:

← 피드로
DEV Community · babycat · 2026-07-25 개발(SW)

A lab card says “No data,” but that phrase could mean no matching record, a disconnected source, a delayed refresh, a filter mismatch, or a request failure. Collapsing those states into an empty chart makes uncertainty look like certainty. The interface needs two layers: what the source reports and what the application currently knows about that report.

OpenAI’s July 23, 2026 announcement says Health in ChatGPT is rolling out on web and iOS to eligible logged-in US users age 18 and older. According to the announcement, supported connections include medical records and Apple Health, while the dashboard can cover labs, medications, activity, sleep, and other health information. OpenAI states connected data and relevant conversations are not used to train foundation models or target ads. This article treats those as attributed statements and proposes a generic UI pattern, not a reconstruction of that interface.

Give each card an evidence state

Do not make color carry the entire message. A card can use this unexecuted TypeScript model:

type SourceState =
  | { kind: "current"; observedAt: string; sourceLabel: string }
  | { kind: "stale"; lastSuccessAt: string; sourceLabel: string }
  | { kind: "disconnected"; sourceLabel: string }
  | { kind: "partial"; available: number; expected?: number }
  | { kind: "error"; retryable: boolean; reference: string };

type MeaningState =
  | { kind: "reported"; display: string; unit?: string }
  | { kind: "missing"; reason: "none_found" | "filtered" | "unknown" }
  | { kind: "unsupported"; explanation: string };

type HealthCard = { title: string; source: SourceState; meaning: MeaningState };

Enter fullscreen mode Exit fullscreen mode

SourceState answers whether retrieval is trustworthy enough to display. MeaningState answers what can honestly be said about the value. Keeping them separate prevents a successful network response from implying interpretation and prevents an error from being shown as a zero.

Semantic card structure

<section aria-labelledby="sleep-title" aria-describedby="sleep-status">
  <h2 id="sleep-title">Sleep</h2>
  <p id="sleep-status">Last updated July 22 at 8:10 AM from connected source.</p>
  <p><strong>395 minutes</strong> <span>reported duration</span></p>
  <details>
    <summary>What this card can and cannot tell you</summary>
    <p>This shows received data. It does not interpret its medical meaning.</p>
  </details>
  <button type="button">Refresh</button>
</section>
<div role="status" aria-live="polite" aria-atomic="true"></div>

Enter fullscreen mode Exit fullscreen mode

Use the live region only for the result of a user-triggered refresh, not every background synchronization. Keep focus on the refresh button after success. On a nonretryable connection failure, move neither focus nor the user into a dead end: expose “Review connection” beside a plain-language explanation.

Content matrix

State Heading text Action Announcement stale “Last updated…” Refresh only after requested refresh disconnected “Source disconnected” Review connection announce transition once partial “Some records unavailable” Show included range do not announce counts repeatedly error “Could not update” Retry when safe include retry result missing “No matching record found” Review filters distinguish from zero

A skeleton loader should reserve layout but must not expose fake values to assistive technology. Disable neither navigation nor disconnect controls while one card refreshes. If several cards fail together, provide a page-level summary with links to affected headings rather than repeating identical alerts.

Keyboard and assistive-technology QA

This is a proposed matrix, not executed results:

Transition Keyboard check Screen-reader check Visual check current to stale action remains reachable freshness text is associated icon plus text changes refresh to error focus stays stable one concise status message error is near card connected to disconnected disconnect remains reversible source name is announced no value shown as current partial to current details state persists heading structure unchanged chart does not jump

Record browser, OS, zoom, contrast mode, and assistive-technology versions when running it. Test at 200% zoom and with CSS disabled to confirm source, freshness, value, and action remain in a sensible reading order.

Boundaries

This pattern does not establish data accuracy, clinical significance, accessibility conformance, product availability, or how any specific service models errors. It does not define whether a value is healthy and should never style a medical conclusion from an AI-generated inference. OpenAI says Health in ChatGPT is designed to support rather than replace medical care, and not for diagnosis or treatment. The interface should preserve that boundary at the value, not bury it in a footer.

AI assistance disclosure: This article was drafted with AI assistance and reviewed against the cited primary source.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다