Show the choice, not just the option label.

`reveal-ui` is a React library for persistent-summary disclosure. It is built for the moments where a select is too cramped and a second modal is too disruptive, especially when a user needs multiple attributes before choosing a property, record, plan, or configuration.

Focus preserved

The parent summary and footer stay mounted while detail opens inline.

Rich comparison

Users compare attributes before they commit, not after.

Nested by design

Group exclusivity, nested close propagation, motion, and scroll are already handled.

Examples

Three small demos that show where the primitive earns its place

These are small, production-shaped examples: edit inline, compare real plan tradeoffs, and run a nested flow without chaining modals.

Inline editor

Edit without replacing the summary

A richer form opens inline while the summary and downstream context stay visible.

Northshore Ops

Escalate only when the target workspace has pending legal review.

Footer context stays visible: next sync in 2 minutes, legal review optional.
Plan comparison

Show the tradeoff, not just the label

Use reveal when the user needs rollout, fit, and caveats before the decision is real.

Current recommendation: Growth

Teams that need more control without enterprise overhead.

$149/mo · 1-week rollout
Nested flow

Close the inner step or the whole chain

A deeper step can open only when needed, then close itself or bubble completion back to the parent flow.

Workspace access flow

Current route: Risk review first

Summary, nested step, and completion action all live in one visible flow.
Docs

Developer docs that read like a real reference surface

The docs are now organized for people first: fast scanning, precise API tables, direct installation guidance, and the lifecycle details you need when the reveal becomes part of real product flow.

Overview
persistent-summary disclosure
inline reveal
nested flows

What the primitive is for and when it earns its place.

Use it when the current workflow should stay in view

`reveal-ui` is for choices that need more than a label before the user can decide. The summary stays visible, the detail opens inline, and the surrounding workflow does not disappear.

Good fit
  • Inline editors that should not replace the summary they are editing.
  • Card stacks where only one item should open at a time.
  • Nested flows that need close propagation without building modal chains.
  • Selection tasks where a label alone hides price, risk, timing, or caveats.
Skip it when
  • A normal accordion already keeps enough context visible.
  • The choice is actually a simple primitive value with no comparison burden.
  • The UI needs a true modal because the surrounding app must become inert.
  • The reveal content should unmount immediately with no phase-aware exit work.

The mental model is top, reveal, bottom

The component is deliberately shaped around three persistent regions instead of one summary block and one hidden panel.

RevealPanel.Top

Summary, heading, and trigger live here. This region stays mounted before, during, and after the reveal.

content

The inserted detail layer. It can be static content or a render function that reads the live reveal phase.

RevealPanel.Bottom

Footer actions, metrics, or summary context that should remain visible below the inserted detail.

Start with one panel and one trigger

This is the smallest useful integration surface for a production app. Start here, then add groups, scroll coordination, or more phase-aware motion as needed.

import * as React from 'react'
import {
  RevealClose,
  RevealPanel,
  RevealTrigger,
  useRevealPanelState,
} from 'reveal-ui'

export function AccountRevealCard() {
  return (
    <RevealPanel
      keepMounted
      magicMotion
      restoreScrollOnClose
      scrollOnOpen
      content={({ phase }) => (
        <div className="border-t border-slate-200 px-5 py-4">
          <StatusInline phase={phase} />
          <RevealClose className="mt-4 rounded-md border px-3 py-2 text-sm">
            Done
          </RevealClose>
        </div>
      )}
    >
      <RevealPanel.Top>
        <div className="rounded-t-3xl border border-slate-200 bg-white px-5 py-4">
          <RevealTrigger className="rounded-md bg-slate-950 px-4 py-2 text-sm text-white">
            Edit inline
          </RevealTrigger>
        </div>
      </RevealPanel.Top>

      <RevealPanel.Bottom>
        <div className="rounded-b-3xl border border-t-0 border-slate-200 bg-slate-50 px-5 py-4 text-sm">
          Footer actions stay visible below the reveal.
        </div>
      </RevealPanel.Bottom>
    </RevealPanel>
  )
}

function StatusInline({ phase }: { phase: string }) {
  const panel = useRevealPanelState()
  return <p className="text-sm text-slate-700">Panel phase: {panel.phase ?? phase}</p>
}
Use `keepMounted` when the revealed subtree itself needs to see `closed` and `closing` instead of unmounting between cycles.
Research

Research notes behind the framing

The framing on the page is backed by guidance on select controls, modal dialogs, and search discoverability rather than vague UX folklore.

FAQ

Short answers for the questions teams ask first

The component is unusual on purpose. The questions below cover what it is, what it replaces, and when it earns its place.