Admin Detail
Full-page, read-oriented detail RECORD for the admin-shell main column — identity header, key-value sections, an optional sensitive/reveal panel, and sub-list slots.
Preview
Artist
Nadia Reyes
Status: ActiveTechno · Berlin / New York · Booking via Animal
Profile
- Legal name
- Nadia Reyes
- Agency
- Animal Bookings
- Home base
- Brooklyn, NY
- Availability
- Status: Booking
Booking terms
Standard engagement rates and rider requirements.
- Base fee
- $4,500per set
- Set length
- 2 hours
- Travel buyout
- $1,200
- Deposit
- 50%on signing
Confidential
Tax & banking
W-9 and payout details. Revealed only when needed.
W-9 and banking details are hidden for privacy.
Booking history
- Sat, Warehouse — Bushwick$4,000Status: Completed
- Fri, Basement — Ridgewood$3,200Status: Completed
- Sat, Main Room — Brooklyn$4,500Status: Scheduled
Installation
npx visor add --block admin-detailThis copies files into your project:
blocks/admin-detail/admin-detail.tsx— the block componentblocks/admin-detail/admin-detail.module.css— the styles
The registry pulls in key-value-list, status-badge, switch, and separator as dependencies.
When to use
AdminDetail is the full-page, read-oriented sibling to admin-detail-drawer. Where the drawer slides a single record in from the right for quick inline edits, AdminDetail renders a record as a main-column page in the admin shell — an identity header, grouped key-value facts, sensitive data behind a reveal gate, and sub-ledgers beneath.
- Use
AdminDetailfor a record's canonical detail page — profile, account, or entity view with grouped facts and history. - Use
admin-detail-drawerfor edit-in-place from a list without navigating away. - Use
admin-settings-pagefor a full-page editor with save/cancel.
Usage
'use client';
import { AdminDetail } from '@/blocks/admin-detail/admin-detail';
import { Avatar, AvatarFallback } from '@/components/ui/avatar/avatar';
import { StatusBadge } from '@/components/ui/status-badge/status-badge';
import { Button } from '@/components/ui/button/button';
export function ArtistDetail({ artist }: { artist: Artist }) {
return (
<AdminDetail
eyebrow="Artist"
title={artist.name}
subtitle={artist.genre}
status="active"
media={
<Avatar size="lg">
<AvatarFallback>{artist.initials}</AvatarFallback>
</Avatar>
}
actions={<Button size="sm">Book</Button>}
sections={[
{
id: 'profile',
title: 'Profile',
columns: 2,
items: [
{ label: 'Legal name', value: artist.legalName },
{ label: 'Agency', value: artist.agency },
{ label: 'Home base', value: artist.homeBase },
],
},
]}
sensitive={{
title: 'Tax & banking',
hiddenNote: 'W-9 and banking details are hidden for privacy.',
items: [
{ label: 'Tax ID (EIN)', value: artist.taxId },
{ label: 'Payout method', value: artist.payout },
],
}}
>
{/* Any sub-list: booking history, invoice ledger, notes… */}
</AdminDetail>
);
}Anatomy
The block is a vertical stack, top to bottom:
- Identity header —
media(Avatar / logo),eyebrow,title,subtitle, astatusslot,breadcrumb, and right-alignedactions. A hairline divider closes the header (suppress withhideHeaderDivider). Replace the whole header withheaderfor custom chrome. - Key-value sections — each entry in
sectionsrenders a titled block that composesKeyValueListfrom itsitems, plus arbitrarycontentfor a sub-list. - Sensitive / reveal panel — the optional
sensitiveprop renders a bordered panel whose contents stay hidden behind aSwitchuntil revealed. - Sub-list slots —
childrenappended after the sections for ledgers, history tables, or notes.
Regions are separated by Separator hairlines.
Composition
AdminDetail composes blessed Visor components rather than reinventing them:
KeyValueListrenders every section'sitems(label/value pairs, with optionalhint).StatusBadgerenders the headerstatuswhen you pass a status string (e.g.status="active"); pass any other node to render it verbatim.Switchgates the sensitive panel's reveal.Separatordraws the dividers between regions.
The sensitive / reveal panel
Sensitive fields — tax IDs, banking, W-9 status — should not be visible by default. The sensitive prop renders a panel that keeps its items and content hidden until the reveal Switch is toggled on:
sensitive={{
eyebrow: 'Confidential',
title: 'Tax & banking',
hiddenNote: 'W-9 and banking details are hidden for privacy.',
items: [
{ label: 'Tax ID (EIN)', value: '**-***4821' },
{ label: 'Payout method', value: 'ACH · Chase ****2210' },
],
}}The reveal state is uncontrolled by default (starts hidden, set defaultRevealed to override). Pass revealed + onRevealedChange to control it externally — for example to log an audit event whenever an operator unmasks the data.
Accessibility
- The identity title is the page
<h1>; each section title is an<h2>. - The reveal
Switchis labeled and wired to the panel body viaaria-controls. - Sections carry stable
idanchors so you can deep-link to a region.
Props
See AdminDetailProps in blocks/admin-detail/admin-detail.tsx for the full list. In summary:
- Identity —
title(required),eyebrow,subtitle,media,status,breadcrumb,actions,header,hideHeaderDivider. - Body —
sections(each withitems,columns,orientation,density,content),sensitive,children. - Layout —
maxWidth.
About Blocks
Blocks are complete UI patterns made up of multiple Visor components. Unlike individual components, blocks represent larger, composed sections of UI — such as admin shells, detail records, or dashboard panels.
Blocks are copy-and-own, just like components. Install them into your project and customize freely.
Admin Dashboard
Drop-in admin overview composition — PageHeader, responsive stat grid, optional secondary region, and ActivityFeed with empty-state fallback.
Admin Detail Drawer
Right-side slide-out panel for viewing or editing a single record, with sticky save/cancel footer, async save handler, and an unsaved-changes guard.