Lite vs Full Managers

Read-only Lite variants of the three Manager components — when to use them and what they save.

Overview

Version 3.8 of @tantainnovative/ndpr-toolkit introduces three new Lite variants of the heavy Manager components: LawfulBasisTrackerLite, ROPAManagerLite, and CrossBorderTransferManagerLite. Each one renders the same list-and-summary view as its Full counterpart, minus every write affordance — no Add, Edit, Archive, Delete, or CSV export. They are purpose-built for read-only surfaces.

The Full components are unchanged. Lite is strictly additive: it ships under a new /lite subpath alongside each feature module, so existing imports keep working exactly as before.

Who is this for?

  • Internal compliance dashboards where most users have view-only access.
  • Customer-facing transparency pages that disclose processing activities or cross-border transfers.
  • Audit or review pages where a separate workflow performs the writes.
  • Embedded widgets — e.g. an “active transfers” tile on a home dashboard.

Bundle size comparison

The heavier the Full component, the bigger the win from Lite. The cross-border manager is the standout — almost the entire Full bundle is the 624-row country adequacy dataset, which Lite does not import.

ModuleFull subpathLite subpathFullLiteSaved
Lawful Basis/lawful-basis/lawful-basis/lite36.7 KB12.7 KB65%
Cross-Border/cross-border/cross-border/lite53.3 KB5.6 KB89%
ROPA/ropa/ropa/lite36.9 KB13.2 KB64%

Sizes are minified and tree-shaken but pre-gzip. Gzipped delivery sizes are roughly 25–40% of these numbers.

When to use Lite

Reach for Lite when:

  • You are rendering a read-only dashboard, audit page, or compliance overview.
  • The page is server-rendered and the viewing user cannot edit anyway (e.g. an executive summary).
  • You are embedding a compliance widget on a homepage or layout shell where bundle weight matters.
  • You are building a customer-facing transparency page disclosing transfers or processing activities.
  • Write operations live in a separate admin route that loads the Full component on demand.

Stick with the Full component when:

  • The same page needs Add, Edit, Archive, or Delete.
  • You rely on the built-in CSV export.
  • You need the built-in detail view or validation handlers.

Side-by-side example

Compare the same Lawful Basis page written against the Full component and against the Lite variant. Lite drops all the write callbacks and surfaces one optional onActivityClick for row interactivity.

Full — read + write

import {
  LawfulBasisTracker,
  useLawfulBasis,
} from '@tantainnovative/ndpr-toolkit/lawful-basis';

export function LawfulBasisPage() {
  const {
    activities,
    addActivity,
    updateActivity,
    archiveActivity,
  } = useLawfulBasis();

  return (
    <LawfulBasisTracker
      activities={activities}
      onAddActivity={addActivity}
      onUpdateActivity={updateActivity}
      onArchiveActivity={archiveActivity}
    />
  );
}

Lite — read-only

import { LawfulBasisTrackerLite } from
  '@tantainnovative/ndpr-toolkit/lawful-basis/lite';
import { useLawfulBasis } from
  '@tantainnovative/ndpr-toolkit/hooks';

export function LawfulBasisOverview() {
  const { activities } = useLawfulBasis();

  return (
    <LawfulBasisTrackerLite
      activities={activities}
      onActivityClick={(a) =>
        router.push(`/lawful-basis/${a.id}`)
      }
    />
  );
}

The Lite version saves ~24 KB on this page alone — and the saving compounds across the three modules.

Per-module usage

Lawful Basis

import { LawfulBasisTrackerLite } from
  '@tantainnovative/ndpr-toolkit/lawful-basis/lite';
import type { ProcessingActivity } from
  '@tantainnovative/ndpr-toolkit';

export function LawfulBasisOverview({ activities }: {
  activities: ProcessingActivity[];
}) {
  return (
    <LawfulBasisTrackerLite
      activities={activities}
      onActivityClick={(a) => console.log('view', a.id)}
    />
  );
}

ROPA

import { ROPAManagerLite } from
  '@tantainnovative/ndpr-toolkit/ropa/lite';
import type { ProcessingRecord } from
  '@tantainnovative/ndpr-toolkit';

export function ROPAOverview({ records }: {
  records: ProcessingRecord[];
}) {
  return (
    <ROPAManagerLite
      records={records}
      onRecordClick={(r) => console.log('view', r.id)}
    />
  );
}

Cross-Border Transfers

import { CrossBorderTransferManagerLite } from
  '@tantainnovative/ndpr-toolkit/cross-border/lite';
import type { CrossBorderTransfer } from
  '@tantainnovative/ndpr-toolkit';

export function TransfersOverview({ transfers }: {
  transfers: CrossBorderTransfer[];
}) {
  return (
    <CrossBorderTransferManagerLite
      transfers={transfers}
      onTransferClick={(t) => console.log('view', t.id)}
    />
  );
}

Migration from Full to Lite

Migrating a read-only page is mechanical and isolated to the import statement and the prop set:

  • Lawful Basis. Replace from '@tantainnovative/ndpr-toolkit/lawful-basis' with from '@tantainnovative/ndpr-toolkit/lawful-basis/lite', drop onAddActivity / onUpdateActivity / onArchiveActivity callbacks, and add onActivityClick if you want row interactivity.
  • ROPA. Replace from '@tantainnovative/ndpr-toolkit/ropa' with from '@tantainnovative/ndpr-toolkit/ropa/lite', drop onAddRecord / onUpdateRecord / onArchiveRecord / onExportCSV callbacks, and add onRecordClick if you want row interactivity.
  • Cross-Border. Replace from '@tantainnovative/ndpr-toolkit/cross-border' with from '@tantainnovative/ndpr-toolkit/cross-border/lite', drop onAddTransfer / onUpdateTransfer / onTerminateTransfer callbacks, and add onTransferClick if you want row interactivity.

The unstyled prop and classNames slot object are still supported on every Lite component. The slot list is shorter — only the slots actually used by the list-and-summary view are present.

Caveats

  • No mutation. Lite components never call a util that mutates state. There is no built-in form, validation handler, modal, or CSV exporter. If you need any of those, render the Full component on the page that needs them — or load it lazily on user intent.
  • Cross-border reads adequacyStatus directly. The Lite cross-border component displays transfer.adequacyStatus straight from each transfer record. It does notrecompute adequacy by looking up the destination country in the bundled adequacy map — that map is the bulk of the Full component's 53 KB and is deliberately excluded. If your records contain stale adequacy data, the display will reflect that; keep the value fresh server-side (e.g. via validateTransfer from /server) before persisting.
  • Type compatibility. Lite consumes the same ProcessingActivity, ProcessingRecord, and CrossBorderTransfer shapes as the Full versions — so swapping is safe at the type level.

See also