View Organization Block
ViewOrganization is a key-value view block built on MUI with a bordered header (title and optional action button), optional subheader.
Installationโ
- npm
- yarn
- pnpm
- bun
npm install @nodeblocks/frontend-view-organization-block
yarn add @nodeblocks/frontend-view-organization-block
pnpm add @nodeblocks/frontend-view-organization-block
bun add @nodeblocks/frontend-view-organization-block
What You Needโ
| Item | Why it matters |
|---|---|
labels.headerTitle | Organization name in the header |
data | Company fields as a Record<string, ReactNode> (row keys become labels) or ReactNode[] for value-only rows |
labels.subheaderTitle (optional) | Secondary line under the header (for example founding date or tagline) |
labels.headerActionButton + headerAction (optional) | Outlined header button label and click handler |
layout (optional) | one-column stacks key/value rows; two-column shows them side by side (default) |
ViewOrganization does not own organization state โ pass labels, data, and optional headerAction from your page. Object data keys become row labels; values can be strings or React nodes (multi-line copy, links, layouts). Set labels.headerActionButton and headerAction to show the header action button with a handler.
Code Examplesโ
- Quick Start
- Labels
- Layouts
- Compound Components
- Block Override
function Example() { const labels = { headerTitle: 'Co-Lift Inc.', }; const data = { Industry: 'Services', Website: 'https://www.co-lift.com/', Overview: 'Co-Lift focuses on essential perspectivesโturning business assets into product ideas, from strategy through development.', 'Business focus': 'End-to-end product development with full-stack engineering to solve customer challenges.', Founded: 'September 11, 2017', Leadership: 'Kanta Kinoshita, CEO ยท Keigo Sadajima, CEO', }; return <ViewOrganization labels={labels} data={data} />; }
Customize header copy, subheader, header action, row content, and layout.
function Example() { const [lastAction, setLastAction] = React.useState(''); const labels = { headerTitle: 'Co-Lift Inc.', subheaderTitle: 'Founded September 11, 2017 ยท Tokyo, Japan', headerActionButton: 'Edit organization', }; const data = { Headquarters: '604 Yoyogi 5-chome, Shibuya-ku, Tokyo 151-0053', Phone: '03-6821-0661', Website: ( <Typography component="a" href="https://www.co-lift.com/" target="_blank" rel="noopener noreferrer" variant="body2" sx={{ color: 'primary.main', fontWeight: 600, textDecoration: 'none', '&:hover': { textDecoration: 'underline' } }} > www.co-lift.com </Typography> ), Industry: 'Services', Employees: '6', Overview: 'Strategy-to-development partner for product and business innovation.', }; return ( <Box> <ViewOrganization labels={labels} data={data} layout="two-column" headerAction={() => setLastAction('Edit organization')} /> {lastAction ? ( <Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 1 }}> Last action: {lastAction} </Typography> ) : null} </Box> ); }
Put headerTitle, subheaderTitle, and headerActionButton on the root labels object (or on ViewOrganization.Header / ViewOrganization.HeaderActionButton in compound layouts). Row labels come from data object keys.
Try different layouts.
function Example() { const [layout, setLayout] = React.useState('two-column'); const labels = { headerTitle: 'Co-Lift Inc.', subheaderTitle: 'Founded September 11, 2017', }; const data = { Headquarters: 'Shibuya-ku, Tokyo', Phone: '03-6821-0661', Industry: 'Services', Employees: '6', Website: 'https://www.co-lift.com/', Founded: 'September 11, 2017', }; return ( <Box> <Box sx={{ display: 'flex', gap: 1, mb: 2 }}> <Box component="button" type="button" onClick={() => setLayout('two-column')} sx={{ px: 1.5, py: 0.75, borderRadius: 1, border: '1px solid', borderColor: layout === 'two-column' ? 'primary.main' : 'divider', bgcolor: layout === 'two-column' ? 'primary.main' : 'background.paper', color: layout === 'two-column' ? 'primary.contrastText' : 'text.primary', cursor: 'pointer', fontSize: 14, fontWeight: layout === 'two-column' ? 600 : 400, }} > Two column </Box> <Box component="button" type="button" onClick={() => setLayout('one-column')} sx={{ px: 1.5, py: 0.75, borderRadius: 1, border: '1px solid', borderColor: layout === 'one-column' ? 'primary.main' : 'divider', bgcolor: layout === 'one-column' ? 'primary.main' : 'background.paper', color: layout === 'one-column' ? 'primary.contrastText' : 'text.primary', cursor: 'pointer', fontSize: 14, fontWeight: layout === 'one-column' ? 600 : 400, }} > One column </Box> </Box> <ViewOrganization labels={labels} data={data} layout={layout} /> </Box> ); }
two-column (default) shows each field label and value side by side. one-column stacks the label above the value with relaxed padding โ useful on narrow viewports or long-form company profiles.
Compose ViewOrganization.Header, ViewOrganization.Subheader, and ViewOrganization.ItemList directly. Pass labels and headerAction on children instead of only on the root; keep data on the root ViewOrganization.
function Example() { const [lastAction, setLastAction] = React.useState(''); const data = { Headquarters: 'Shibuya-ku, Tokyo', Phone: '03-6821-0661', Industry: 'Services', Employees: '6', Website: 'https://www.co-lift.com/', }; return ( <Box> <ViewOrganization layout="two-column"> <ViewOrganization.Header labels={{ headerTitle: 'Co-Lift Inc.', headerActionButton: 'Edit organization', }} headerAction={() => setLastAction('Edit organization')} sx={{ px: 2, py: 1.5, bgcolor: 'grey.50', borderRadius: 2, border: '1px solid', borderColor: 'divider', }} /> <ViewOrganization.Subheader labels={{ subheaderTitle: 'Founded September 11, 2017' }} sx={{ px: 2, fontStyle: 'italic', color: 'text.secondary' }} /> <ViewOrganization.ItemList data={data} sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 2, overflow: 'hidden', '& .MuiListItem-root': { bgcolor: 'background.paper' }, }} /> </ViewOrganization> {lastAction ? ( <Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 1 }}> Last action: {lastAction} </Typography> ) : null} </Box> ); }
Use function children with defaultBlocks and defaultBlockOrder to inject blocks, replace defaults, and control order.
function Example() { const [noticeVisible, setNoticeVisible] = React.useState(true); const labels = { headerTitle: 'Co-Lift Inc.', subheaderTitle: 'Profile review in progress', }; const data = { Headquarters: 'Shibuya-ku, Tokyo', Phone: '03-6821-0661', Industry: 'Services', Employees: '6', }; return ( <ViewOrganization labels={labels} data={data}> {({ defaultBlocks, defaultBlockOrder }) => ({ blocks: { ...defaultBlocks, orgNotice: noticeVisible ? ( <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2, px: 2, py: 1.5, mb: 1, borderRadius: 2, bgcolor: 'info.main', color: 'info.contrastText', }} > <Typography variant="body2" sx={{ fontWeight: 600 }}> Organization details were updated recently </Typography> <Box component="button" type="button" onClick={() => setNoticeVisible(false)} aria-label="Dismiss notification" sx={{ flexShrink: 0, border: '1px solid rgba(255,255,255,0.35)', bgcolor: 'rgba(255,255,255,0.12)', color: 'inherit', borderRadius: '50%', width: 28, height: 28, cursor: 'pointer', fontSize: 16, lineHeight: 1, }} > ร </Box> </Box> ) : null, header: ( <ViewOrganization.Header labels={labels} sx={{ px: 2, py: 2, borderRadius: 2, border: '1px solid', borderColor: 'divider', bgcolor: 'background.paper', }} /> ), itemList: ( <ViewOrganization.ItemList data={data} sx={{ mt: 2, border: '1px solid', borderColor: 'divider', borderRadius: 2, '& .MuiListItem-root:nth-of-type(even)': { bgcolor: 'grey.50' }, }} /> ), }, blockOrder: [ ...(noticeVisible ? ['orgNotice'] : []), 'header', 'subheader', 'itemList', ], })} </ViewOrganization> ); }
When to use block overrides
Default defaultBlockOrder is header, subheader, itemList, item, itemKey, itemValue. The default render uses itemList to map data; the separate item / itemKey / itemValue entries are for granular overrides. This example prepends a dismissible orgNotice, replaces header and itemList with styled variants, and omits unused block keys from blockOrder.
Important Propsโ
Core Propsโ
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
data | Record<string, ReactNode> | ReactNode[] | No | undefined | Row content: object keys become field labels; arrays render value-only rows |
labels | { headerTitle?: string; headerActionButton?: string; subheaderTitle?: string } | No | undefined | Header title, optional action button label, and subheader copy |
Content Propsโ
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
labels.headerTitle | string | No | undefined | Main heading in ViewOrganization.Header |
labels.subheaderTitle | string | No | undefined | Secondary line under the header (ViewOrganization.Subheader) |
labels.headerActionButton | string | No | undefined | Label for the outlined header button; shown when labels.headerActionButton or headerAction is set (or passed on ViewOrganization.HeaderActionButton) |
headerAction | () => void | No | undefined | Invoked when the default header action button is clicked (after any onClick on the button) |
layout | 'one-column' | 'two-column' | No | 'two-column' | Row layout: stacked key/value vs side-by-side columns |
Layout and Composition Propsโ
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | BlocksOverride | ReactNode | No | undefined | Compound JSX children or function override returning blocks and blockOrder |
className | string | No | undefined | Class name on the root stack (nbb-view-organization) |
sx | SxProps | No | undefined | MUI system styles for the root stack (default render includes margin: 'auto') |
ViewOrganization inherits StackProps (except children). Default defaultBlockOrder: header, subheader, itemList, item, itemKey, itemValue.
Sub-component propsโ
Sub-components read from context and accept the same content keys as props to override locally.
| Sub-component | Main Props | Inherits | Built on |
|---|---|---|---|
ViewOrganization.Header | labels (headerTitle, headerActionButton), headerAction, children, className, sx | StackProps | Stack + Typography + optional ViewOrganization.HeaderActionButton |
ViewOrganization.HeaderActionButton | labels (headerActionButton), headerAction, children, className, onClick | ButtonProps | Button (variant="outlined", size="medium") |
ViewOrganization.Subheader | labels (subheaderTitle, headerTitle, headerActionButton), children, className, sx | StackProps | Stack + Typography |
ViewOrganization.ItemList | data, children, className, sx | ListProps | List (component="dl") + ViewOrganization.Item rows |
ViewOrganization.Item | layout, children, className, sx | ListItemProps | ListItem |
ViewOrganization.Item.Key | layout, children, className, sx | TypographyProps | Typography (component="dt", variant="subtitle1") |
ViewOrganization.Item.Value | layout, children, className, sx | TypographyProps | Typography (component="dd", variant="body2") |
Default UI Blocksโ
| Block | Built on | Notes |
|---|---|---|
ViewOrganization (root) | Stack | Column layout with spacing={3}, margin: 'auto' (nbb-view-organization) |
header (ViewOrganization.Header) | Stack | Renders when labels.headerTitle, labels.headerActionButton, or custom children is set; default styling adds bottom border, py: 3, mb: 3; includes ViewOrganization.HeaderActionButton when headerAction or labels.headerActionButton is set |
subheader (ViewOrganization.Subheader) | Stack | Renders when labels.subheaderTitle or custom children is set |
itemList (ViewOrganization.ItemList) | List | Maps data object entries or array values to key/value rows |
Default root render order: header โ subheader โ itemList.
TypeScriptโ
import * as React from 'react';
import { ViewOrganization } from '@nodeblocks/frontend-view-organization-block';
import type { ReactNode } from 'react';
type OrganizationLabels = {
headerTitle?: string;
headerActionButton?: string;
subheaderTitle?: string;
};
type OrganizationData = Record<string, ReactNode>;
export function OrganizationDetailView() {
const labels: OrganizationLabels = {
headerTitle: 'Co-Lift Inc.',
subheaderTitle: 'Founded September 11, 2017',
headerActionButton: 'Edit organization',
};
const data: OrganizationData = {
Headquarters: 'Shibuya-ku, Tokyo',
Phone: '03-6821-0661',
Industry: 'Services',
Website: 'https://www.co-lift.com/',
};
return (
<ViewOrganization
labels={labels}
data={data}
headerAction={() => {
/* navigate or open edit dialog */
}}
/>
);
}