@cybercommand/cyberbrein-ui (0.14.0)
Installation
@cybercommand:registry=npm install @cybercommand/cyberbrein-ui@0.14.0"@cybercommand/cyberbrein-ui": "0.14.0"About this package
@cybercommand/cyberbrein-ui
Status: current Doelgroep: consumerontwikkelaars en UI Kit maintainers Owner: UI Kit maintainers Last verified: 2026-07-11 Source of truth: package exportmap, TypeScript-public API, CSS/tokens en tests
Interne maintainer-, theming-, toegankelijkheids- en release-uitleg: docs/README.md.
Gedeelde UI-componenten en theming voor Cyberbrein tenant-apps (Next.js web/BFF).
Product-specifieke schermen blijven in de app; shell, data-primitives, formulierstijlen en
theme-tokens komen uit dit package zodat product:create geen kopieën hoeft te onderhouden.
Quick Start
pnpm install --frozen-lockfile
pnpm verify
Installatie (nieuw product via product:create)
Het product-template bevat al de juiste wiring. Voor handmatige setup:
1. Package dependency
In apps/<product>/apps/web/package.json:
{
"dependencies": {
"@cybercommand/cyberbrein-ui": "^0.1.0"
}
}
During local multi-repo development you may temporarily use a link: override,
but committed product repos should depend on a published version.
2. Next.js transpile
In next.config.mjs:
const nextConfig = {
transpilePackages: ['@cybercommand/cyberbrein-ui'],
};
3. Tailwind
In tailwind.config.ts:
import type { Config } from 'tailwindcss';
import { cyberbreinUiPreset } from '@cybercommand/cyberbrein-ui/tailwind';
const config: Config = {
content: [
'./src/**/*.{ts,tsx}',
'./node_modules/@cybercommand/cyberbrein-ui/**/*.{js,mjs,ts,tsx}',
],
presets: [cyberbreinUiPreset as Config],
};
export default config;
Pas het node_modules pad aan als je web-app dieper in de boom staat, bijvoorbeeld
../../node_modules/@cybercommand/cyberbrein-ui/**/*.{js,mjs,ts,tsx}.
4. Globale stijlen
In src/app/globals.css (of root layout):
@import '@cybercommand/cyberbrein-ui/styles/globals.css';
5. Per-product theming — theme.config.ts
Bewerk alleen dit bestand in de web-app (niet in het shared package):
import type { NavItem, ThemeConfig } from '@cybercommand/cyberbrein-ui';
import type { Permission } from '@/lib/api-types';
export const themeConfig = {
appName: 'Mijn Product',
tagline: 'Korte beschrijving',
defaultLocale: 'nl-NL',
} satisfies ThemeConfig;
export const navItems: NavItem<Permission>[] = [
{ href: '/dashboard', label: 'Overzicht' },
{ href: '/tasks', label: 'Taken', permission: 'data:read' },
];
Tenant-specifieke accentkleur komt uit de API (primaryColor) en wordt door AppShell /
ThemeProvider als CSS-variabele gezet. Vaste productkleuren kun je in theme.config uitbreiden
met defaultTokens uit het package.
6. App-shell in layout
import { AppShell } from '@cybercommand/cyberbrein-ui';
import { navItems, themeConfig } from '@/components/theme/theme.config';
import { formatRole } from '@/lib/format';
<AppShell
orgName={settings?.displayName ?? 'Tenant'}
primaryColor={settings?.primaryColor}
appName={themeConfig.appName}
navItems={navItems}
permissions={me.permissions}
user={{ email: me.email, role: me.role }}
formatRole={formatRole}
>
{children}
</AppShell>
Exports
Root export (@cybercommand/cyberbrein-ui)
| Categorie | Componenten |
|---|---|
| Shell | AppShell, AppNav, UserMenu, PermissionGate |
| Data | DataTable, EmptyState¹, StatusBadge, ConfirmDialog, Card¹, PageHeader, StatCard |
| Theme | ThemeProvider, defaultTokens, tokensWithPrimaryColor, cssVarNames, tokensToStyle, renderBrandedHtmlPage, types ThemeTokens, ThemeConfig, NavItem |
| Forms | inputClass, btnPrimary, btnSecondary, btnGhost |
| Utils | hasPermission, hasAnyPermission |
renderBrandedHtmlPage — framework-agnostic branded HTML pages
Voor niet-React / niet-Tailwind consumers (bv. een Next.js API-route die een losse
HTML-pagina teruggeeft). Genereert een gebrand HTML-document met defaultTokens /
tokensWithPrimaryColor, zonder dat de consumer zelf hsl/hex-tokensets in een inline
<style>-string hoeft te dupliceren. Heeft geen React (of ander framework) als
dependency, werkt dus ook in een plain Node/edge API-route.
import { renderBrandedHtmlPage } from '@cybercommand/cyberbrein-ui';
export async function GET(request: Request) {
const html = renderBrandedHtmlPage({
title: 'Wachtwoord reset',
bodyHtml: '<main><h1>Check je e-mail</h1><p>We hebben een resetlink verstuurd.</p></main>',
primaryColor: tenant?.primaryColor,
});
return new Response(html, { headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}
Workspace export (@cybercommand/cyberbrein-ui/workspace)
Rijkere workspace-primitives voor in-app schermen. Importeer expliciet uit de
./workspace subpath:
import { Modal, Button, useToast, ToastProvider } from '@cybercommand/cyberbrein-ui/workspace';
| Categorie | Componenten |
|---|---|
| Layout | Card¹, CardHeader, CapabilityCard, EmptyState¹, DetailRow, ProfilePage, Table, TableHeader, TableBody, TableRow, TableHead, TableCell |
| Data tables | TableSelectHead, TableSelectCell, TableEmpty, TableSkeleton, useTableSelection, useTableSort, legacy THead/TH/TD |
| Actions | Button, Badge, StatusDot, statusBadgeTone, Spinner |
| Overlays | Modal (focus-trap, Escape, focus-restore), ConfirmProvider, useConfirm |
| Feedback | ToastProvider, useToast, ErrorBanner, WarningBanner, WarningCallout, SuccessBanner |
| Icons | IconDashboard, IconInbox, IconBriefcase, IconCalendar, IconBuilding, IconSignal, IconKey, IconUserGroup, IconFileText, IconSearch, IconPlus, IconX, IconCheck, IconCheckSquare, IconAlertTriangle, IconMessageCircle, IconClock, IconChevronRight, IconChevronDown, IconMenu, IconInfo, IconArrowUpRight, IconLink, IconStar |
| Types | BadgeTone |
Instance-scoped contributions (@cybercommand/cyberbrein-ui/workspace-contributions)
Nieuwe lege shells gebruiken WorkspaceInstanceContributionHost. Deze additive v2-host accepteert
alleen een vaste WorkspaceInstance en universeel slot; product-, tenant- en workspacefamilyprops
bestaan niet. Zie het hostcontract.
Nieuwe generieke bouwstenen (cross-repo audit)
import {
CapabilityCard,
DetailRow,
StatusDot,
statusBadgeTone,
WarningCallout,
} from '@cybercommand/cyberbrein-ui/workspace';
// DetailRow — label links (muted), waarde rechts (truncate + font-medium), border-bottom.
<DetailRow label="E-mail" value="user@example.com" />
<DetailRow label="Notitie" value={longText} wrap maxWidth="24rem" />
// StatusDot — klein gekleurd statuspunt op basis van BadgeTone, i.p.v. ad-hoc
// 'h-2 w-2 rounded-full bg-emerald-300'-patronen.
<StatusDot tone="success" label="Online" />
// statusBadgeTone — map een willekeurige status-string naar een BadgeTone via een
// door de caller aangeleverde map.
const tone = statusBadgeTone(
{ online: 'success', degraded: 'warning', offline: 'neutral' },
connection.status,
'neutral',
);
<Badge tone={tone}>{connection.status}</Badge>
// WarningCallout — rijkere variant van WarningBanner met optionele title/children/action,
// voor eenmalig-token banners, onzeker-bewijs-notices, approval-blocked-meldingen.
<WarningCallout title="Eenmalig token" message="Bewaar dit token nu, het wordt niet opnieuw getoond.">
<code>{oneTimeToken}</code>
</WarningCallout>
// CapabilityCard — Card met title/description en een enabled/disabled-branch.
<CapabilityCard
title="Automatische export"
description="Exporteer rapportages automatisch naar S3."
enabled={plan.hasAutomation}
disabledNotice={<p>Vereist het Pro-plan.</p>}
>
<ExportSettingsForm />
</CapabilityCard>
ProfilePage + het "Mijn account"-patroon
Elke app hoort naar hetzelfde standaard accountscherm te linken i.p.v. het account-blok in
de sidebar puur decoratief te laten. WorkspaceShellFooter's account.profileHref maakt de
naam/e-mail klikbaar; renderProfileLink gebruikt de router van de host-app (anders valt het
terug op een gewone <a>). De pagina zelf komt van de kit-ProfilePage, met een link naar
Authentik's eigen self-service pagina voor wachtwoord/MFA/sessies — dat blijft bij de identity
provider, deze pagina implementeert dat niet opnieuw.
import { Link } from 'react-router-dom'; // of next/link, afhankelijk van de app
import { ProfilePage, WorkspaceShellFooter } from '@cybercommand/cyberbrein-ui/workspace';
<WorkspaceShellFooter
account={{
initial: me.email.slice(0, 1).toUpperCase(),
primary: me.name ?? me.email,
secondary: me.email,
profileHref: '/account',
signOutHref: '/outpost.goauthentik.io/sign_out',
}}
renderProfileLink={({ href, className, children }) => (
<Link to={href} className={className}>{children}</Link>
)}
/>
// Op de /account-route:
<ProfilePage
name={me.name}
email={me.email}
role={me.role}
permissions={me.permissions}
formatRole={formatRole}
authentikUrl={process.env.AUTHENTIK_URL}
>
{/* product-/tenantspecifieke instellingen, bv. notificatievoorkeuren */}
</ProfilePage>
Overige exports
| Subpath | Inhoud |
|---|---|
./styles/globals.css |
Globale CSS (Tailwind-lagen, .card en .animate-fade-in component/utility-classes) |
./styles/tokens.css |
Semantic tokens en de gedeelde .card, .input en .label surface classes |
./tailwind |
cyberbreinUiPreset / tailwindPreset Tailwind-preset |
¹ Card en EmptyState bestaan in beide exports. De workspace-varianten zijn de
canonieke, rijkere API's; de data-layer varianten zijn @deprecated en verdwijnen in
een toekomstige major-versie. Zie REMEDIATION.md en CHANGELOG.md.
Wat blijft product-specifiek
theme.config.ts— appnaam, navigatie, optionele vaste tokens- Businessforms (
SettingsForm,InviteUserForm, …) - Pagina's en domeincomponenten (
TaskList,UserTable, …) lib/api-types,lib/format,lib/permissions(app API-contract)
Responsive gedrag
AppNav toont een sidebar op lg+ en een horizontale scroll-nav op kleinere viewports.
DataTable scrollt horizontaal onder min-w-[640px]. Deze patronen zitten in het package en
hoeven per product niet opnieuw gebouwd te worden.
Dependencies
Dependencies
| ID | Version |
|---|---|
| @fullcalendar/core | ^6.1.21 |
| @fullcalendar/list | ^6.1.21 |
| @fullcalendar/react | ^6.1.21 |
| @fullcalendar/timegrid | ^6.1.21 |
Development dependencies
| ID | Version |
|---|---|
| @changesets/cli | ^2.31.0 |
| @testing-library/dom | ^10.4.1 |
| @testing-library/react | ^16.3.2 |
| @types/react | ^19.2.17 |
| @types/react-dom | ^19.2.3 |
| @vitejs/plugin-react | ^6.0.3 |
| jsdom | ^29.1.1 |
| next | ^16.2.10 |
| react | ^19.2.7 |
| react-dom | ^19.2.7 |
| tailwindcss | ^3.4.19 |
| typescript | ^6.0.3 |
| vite | ^8.1.4 |
| vitest | ^4.1.10 |
Peer dependencies
| ID | Version |
|---|---|
| next | >=14 |
| react | >=18 |
| react-dom | >=18 |