Bỏ qua tới nội dung
Component / 065 / NEXOFRAME

RecordShell

Mẫu chuẩn

Một bố cục cho mọi màn bản ghi: header, dải giai đoạn tuỳ chọn, một cột rail gập được bằng dữ liệu, và một vùng main do host tự lấp. Thay thế DetailRail cho các màn CRM mới -- DetailRail vẫn còn, xem ghi chú lỗi thời ở trang của nó.

Composite tầng 2Dựng từ AccordionRail là dữ liệu, không phải JSXKhông sở hữu tab

Playground

Đổi "Loại bản ghi" để thấy dải giai đoạn chỉ xuất hiện ở deal, đổi "Trạng thái" để thấy cả bốn trạng thái của rail, và đổi bề rộng khung để thấy rail xếp lên trên main dưới small.

LIVE PREVIEW

Nguyễn Minh Anh

Khách hàng cá nhân

Đang hoạt động

Emailminhanh@khachhang.vn
Điện thoại090 123 4567
Doanh nghiệpCông ty TNHH Phú Gia

Đã gọi xác nhận đơn hàng, khách hẹn nhận hàng thứ Sáu.

Gửi báo giá phiên bản mới qua email.

Host tự dựng Tabs ở đây -- RecordShell chỉ cấp slot main.

Loại bản ghi: "person", trạng thái: "data".

import { RecordShell } from "@nexobox/ui";

<RecordShell
  header={<PageHeader title={record.name} />}
  strip={isDeal ? <FilterTabs ... /> : undefined}
  rail={[
    { id: "contact", title: "Thông tin liên hệ", defaultOpen: true, content: <ContactFields /> },
    { id: "notes", title: "Ghi chú", content: <NotesSection /> },
  ]}
  main={<Tabs>...</Tabs>}
/>

Bài toán

Người, doanh nghiệp và deal dùng cùng một khung trong Pipedrive: header → dải giai đoạn (chỉ deal) → cột rail gập được → vùng chính. P-D15/P-D16 đặt khung đó vào packages/ui dưới tên DetailRail, nhưng khung đó sở hữu tab thay vì cấp slot, nên mỗi host muốn một cách lấp phần phải khác nhau sẽ phải đoán. RecordShell tách rail khỏi quyết định "phần phải là gì" -- host luôn tự dựng main.

Khi nào sử dụng

Nên dùng

Màn chi tiết người, doanh nghiệp hoặc deal: một tập section tham khảo gập được, cộng một vùng chính do host quyết định.

Khi nào không dùng

Tránh dùng

Không dùng choDùng thay
Một trang không có rail, chỉ có nội dung đơnPageHeader + nội dung thường
Vùng phải cố định luôn hiển thị action bar/Focus/History (ba băng của hoạt động)ActivityPane, đặt vào main
Màn chi tiết sản phẩm cũ dựng trên cột-cố-định-cạnh-thân-có-tab mà chưa di trúDetailRail cho tới khi thẻ di trú chạy

Dựng từ

Primitive tầng 1Vai trong composite
AccordionCơ chế gập/mở của rail, không viết lại
RecordShell thêm gì
Bố cục: header, strip tuỳ chọn, cột rail, vùng main
Rail là mảng dữ liệu (CD-D04), không phải JSX lắp tay -- cùng một trang vẽ được người hay doanh nghiệp bằng cách đổi mảng
Xếp chồng dưới small: rail lên trên main

Anatomy

#PhầnGhi chú
1Headerheader, thường là PageHeader. Tên bản ghi là chữ lớn nhất, đậm nhất trên màn.
2Stripstrip, tuỳ chọn. Deal dùng cho dải giai đoạn; người và doanh nghiệp không truyền.
3Railrail: mảng { id, title, content, defaultOpen?, actions? }, mỗi phần tử một section gập được. Nhãn trường trong section dùng caption muted, giá trị dùng body text-primary, căn nhãn phải/giá trị trái.
4Mainmain, một slot. Host tự quyết nội dung -- Tabs, ActivityPane, hoặc văn bản thường.

States

StateHành vi
Có dữ liệuNhãn phải/giá trị trái, mép trái các giá trị thẳng hàng. Xem playground ở "Có dữ liệu".
Trường rỗngMột dấu gạch "–" muted ở cột giá trị thay vì để trống -- xem playground ở "Rỗng", mục Thông tin liên hệ.
Section rỗngEmpty + một hành động tiếp theo, không bao giờ một hộp trống -- xem playground ở "Rỗng", mục Ghi chú.
Đang tảiSkeleton đúng hình dạng cuối cùng -- đúng số dòng, đúng bề rộng cột nhãn/giá trị. Không spinner.
LỗiAlert nội tuyến trong đúng section bị lỗi (ở đây là Ghi chú) -- section Thông tin liên hệ vẫn dùng được bình thường.

Bàn phím & trợ năng

Tiêu đề mỗi section là một nút gập được, thừa hưởng nguyên vẹn focus-visible ring từ AccordionTrigger.
Affordance ở actions (ví dụ nút + của Ghi chú) là một control độc lập ngoài nút gập, tự nhận tiêu điểm riêng.
Composite không thêm một điểm dừng tiêu điểm nào của riêng nó ngoài những gì Accordion đã cấp.

Seam — host sở hữu gì

Composite không biết nó đang hiển thị người, doanh nghiệp hay deal -- không gõ chữ nghiệp vụ ở tầng này. Host sở hữu toàn bộ chữ nghĩa, dữ liệu trong từng section, section nào mở sẵn (defaultOpen), và toàn bộ nội dung main kể cả việc có tab hay không.

API & triển khai

PropMặc địnhQuy ước
header—Bắt buộc. Thường là PageHeader.
stripundefinedDải ngang trên hai cột. Chỉ deal truyền.
rail—Bắt buộc. Mảng { id, title, content, defaultOpen?, actions? }.
main—Bắt buộc. Một slot; host tự dựng Tabs nếu cần.

Design tokens

--nf-foundation-layout-context-panel (bề rộng rail từ small trở lên), --nf-foundation-space-6 (giữa header/strip/hai cột), --nf-foundation-space-4 (giữa các section trong rail và trong main), --nf-foundation-space-3 (giữa các dòng trường trong một section -- do host áp dụng trong content), --nf-foundation-space-2 (giữa nhãn và giá trị trên cùng dòng). small là breakpoint đặt tên duy nhất repo này cho phép literal px (theme.css), cùng ngưỡng xếp chồng mà PageHeader đã dùng. Qua Accordion: --nf-component-accordion-*.

Do / Don't

Nên dùng

Truyền rail như dữ liệu để cùng một trang vẽ được nhiều loại bản ghi. Thiết kế cả bốn trạng thái của nội dung mỗi section.

Tránh dùng

Lắp JSX cố định cho rail thay vì một mảng. Tự dựng tab bên trong một section của rail -- tab chỉ thuộc main.