Skip to content

Visual Baseline

Review the default RNUI visual language in one place — typography, controls, elevated surfaces, and status treatments. Use this page after token or component changes to confirm nothing regressed.

Source of truth: .planning/rnui-design-foundation-contract.md

LayerRule
SurfacesFill + border required; shadow optional depth only
Bordersdefault for shells, input for fields, subtle for dividers — all perceptible
Radiuslg buttons/inputs, xl cards/modals — not pill-by-default
ShadowSoft mobile-native elevation; no Bootstrap black slabs
Statusbg + border + text on every severity
StatesFocus, disabled, pressed, selected use semantic tokens

Native example app is the source of truth — CSS previews below approximate tokens. Run the SurfaceVisibility screen in apps/example after token changes.

Automated guardrail: bun run build && bun run surface:audit

FamilyPass criteria
Layout (Card, Paper, Divider)Visible with shadow.none
Actions (Button, Toggle)Outline/ghost/disabled readable
Forms (Input, FormGroup)Visible inside Card
Status (Badge, Alert, Toast)bg + border + text
Overlay (Modal, Menu, Select)Panel border + fill
Data (List, Table, Tabs)Row/tab separation without shadow-only

Hierarchy should feel mobile-native: clear steps without overpowering body copy.

Type scale

Display through caption in a realistic content block

Design systems that feel native

RNUI pairs semantic tokens with polished components so your product reads consistently on iOS and Android without reinventing spacing, color, or type on every screen.

Why teams choose RNUI

Ship faster with accessible defaults, subtle elevation, and motion that respects reduced-motion preferences.

Updated 2 days ago · 4 min read

Default radius is rounded-lg (not pill). Solid actions stay premium with soft elevation; outline and ghost stay lightweight.

Button variants

Hero card plus solid · outline · ghost · destructive

Upgrade to Pro

Unlock offline mode, shared workspaces, and priority support for your team.

Start free trialLearn more
PrimaryOutlineGhostDelete

Native-friendly 44px height (aligned with Button md), soft borders, and readable placeholder text.

Profile form

Label, helper text, and error state

Continue

Elevated surfaces use subtle border + soft shadow — border and fill must remain visible with shadow disabled (see No-shadow section below).

Settings card

Realistic profile / product layout

Alex Morgan

Product designer · San Francisco. Usually replies within a few hours.

MessageView profile

Weekly summary

12 tasks completed · 3 meetings · Focus time up 18% from last week.

Every variant includes background, border, and text so pills read on normal app backgrounds.

Badge variants

default · brand · accent · success · warning · error · info

On app background

ShippedDelayedFailedIn transit
#1042 — Studio deskDelivered
#1041 — Monitor armProcessing
#1040 — Cable kitDraft
SubscriptionPro
SecurityAction needed
DefaultBrandAccentSuccessWarningErrorInfo

Status surfaces stay refined — elevated toast and snackbar cards (not heavy inverse slabs). Alerts use severity borders on standard variant.

Feedback & toggles

Chips, alerts, toast, snackbar, switch, and checkbox

ProductDraftFilterLive

New version available

Update to 2.4 for faster sync and improved offline mode.

Payment method expiring

Your card ends in 12 days. Update billing to avoid interruption.

Profile saved

Your changes are live across all devices.

Could not upload photo

Check your connection and try again.

Changes savedUndo

Status components must be visible without relying on iOS glass, blur, notification-shade blending, or dark overlays.

Visibility matrix

Badges, chips, and compact alerts on five surfaces

White surface

DefaultBrandAccentSuccessWarningErrorInfo
BrandNeutralActive

Synced

Failed

App background

DefaultBrandAccentSuccessWarningErrorInfo
BrandNeutralActive

Synced

Failed

Card surface

DefaultBrandAccentSuccessWarningErrorInfo
BrandNeutralActive

Synced

Failed

Glass surface

DefaultBrandAccentSuccessWarningErrorInfo
BrandNeutralActive

Synced

Failed

Dark surface

DefaultBrandAccentSuccessWarningErrorInfo
BrandNeutralActive

Synced

Failed

  1. Background — status fill must differ from the surface behind it
  2. Border — 1px semantic border defines the edge
  3. Text — semantic text color stays readable (WCAG AA on the fill)
  4. No blur dependency — if a badge only looks correct over glass, the tokens are wrong
SurfaceToken reference
White#FFFFFF
App backgroundcolor.bg.default
Cardcolor.surface.raised
Glasscolor.glass.surface
Darkcolor.surface.default (dark)

CSS demos above approximate tokens — overlays must be verified in the example app on iOS and Android.

ComponentExample screenNative checks
Modalapps/example/app/components/Modal.tsxInset, safe area, keyboard form, animation
DialogDialog.tsxHost inset, actions slot, form input
AlertDialogAlertDialog.tsxDestructive confirm, button layout
AlertAlert.tsxCompound title + body severity colors

Run: cd apps/example && bun run ios (or android). Full checklist: Example app guide.

Light + dark on iPhone-sized simulator and one Android emulator:

  1. Modal/Dialog never flush to screen edges (host inset visible)
  2. Form-in-modal: primary action stays above keyboard (iOS)
  3. Alert title + body share severity hue without manual color props
  4. Toast action label readable; Snackbar uses elevated surface
  5. Badge default and accent readable on app background
  6. Backdrop tap and hardware back dismiss where onClose is set

Repo copy: .planning/device-qa-checklist.md

Components must remain visible when shadow/elevation is disabled. Shadow may add depth but must never be required for recognition.

No-shadow matrix

Card, Paper, Badge, Chip, Alert, Input, and outline/ghost/disabled buttons — shadow stripped

App background

Card · shadow none

Paper · elevation none

DefaultSuccessError
SolidOutlined

Info alert

Visible without shadow.

Card surface

Card · shadow none

Paper · elevation none

DefaultSuccessError
SolidOutlined

Info alert

Visible without shadow.

White surface

Card · shadow none

Paper · elevation none

DefaultSuccessError
SolidOutlined

Info alert

Visible without shadow.

Glass surface

Card · shadow none

Paper · elevation none

DefaultSuccessError
SolidOutlined

Info alert

Visible without shadow.

Dark surface

DefaultSuccessError
SolidOutlined

Info alert

Visible without shadow.

ComponentNo-shadow check
CardWhite fill + border.default on bg.default
PaperBorder + fill at elevation none
Badge / ChipFill + border on app, card, and glass panels
AlertSeverity bg + 1px border
Inputsurface.default fill + border.input
Button outline/ghostBorder or brand text — not shadow-dependent
DisabledReduced opacity but still readable
  • App background (color.bg.default)
  • White / card surface (color.surface.default / raised)
  • Glass-like panel (color.surface.glass)
  • Dark panel (color.bg.inverse or dark surface.default)

Native QA: example app screen SurfaceVisibility — full A–G matrix (neutral, form, status, action, data, overlay notes, dark panel) with real RNUI components.

Hard rules enforced by tokens, component recipes, and bun run surface:audit:

  1. Fill first — component background must differ from the parent canvas (bg.default, surface.default, or surface.raised) without relying on shadow.
  2. Border required — 1px semantic border (border.default, border.input, or status border) must remain perceivable on light and dark surfaces.
  3. Shadow is optional depth — shadow.sm and up may enhance elevation; removing shadow must not hide the component.
  4. Status triple — Badge, Chip, Alert, Toast variants need background + border + text on app, white, card, glass, and dark panels.
  5. Nested surfaces — Card-on-Card uses surface.raised inner fill; FormGroup grouped uses outer border; Input keeps border.input inside Card.
  6. Glass fallback — translucent fills (surface.glass) pair with visible surface.glassBorder.
  7. Brand themes — bg.default and surface.default must not collapse; borders strengthened per brand tint.

Reference docs: .planning/surface-visibility-contract.md · audit: scripts/audit-surface-contrast.mjs

Final truth is the native example app — CSS demos approximate tokens; run SurfaceVisibility on iOS/Android simulators after token changes.