Search nx-ui
Jump to any foundation, component, block or example.
Changelog
Every change to the registry, newest first — one entry per merged PR, tagged with the items it touched.
Machine-readable copies: llms-changelog.txt (full history) and r/versions.json (per-item content hashes for drift detection — see For agents).
- Changed#90
Registry dependencies now use Base UI 1.9, Motion 14 and refreshed table, map, icon, markdown and rendering packages; the TanStack legacy table bridge remains supported. The configured shadcn `cn` engine preserves Nexus display-type merging and the `cx` alias, and native private GitHub installation now resolves the full component dependency graph without namespace setup. Both registry entry points and every shipped TypeScript source are checked under strict consumer settings before release.
- Fixed#90
Schema paths and parameter names render as escaped text, preserving parameter highlighting without interpreting API-provided content as HTML. Custom React children also render normally.
ai-schema-display - Added#90
Added shadcn Questionnaire for multi-step clarification and an opt-in Base UI Toast provider and manager. Sonner remains supported; install Toast only where its provider, action, or promise lifecycle is useful. A deterministic agent-workflow example shows clarification, approval, progress, rejection, failure, and result states.
The fallback catalogue calls the former Nexus Files entry Nexus Projects and uses the `projects` identifier; consumers matching the old `files` identifier should update their lookup. Showcase examples and catalogue tests use the same identifier and destination. This completes the rename proposed in PR #87 without changing identity-service authority or granting access to an application.
- Changed#90
User Menu now supports a compact avatar trigger, configurable popup placement and a Manage organisations link, with a complete Assurance-style profile menu example. Appearance choices show text alongside their icons; organisation switching exposes the current selection to assistive technology and disables unavailable switches.
- Fixed#90
Shipped components now handle empty or incomplete input arrays consistently, including empty market timelines and route fixtures. Generated terrain and stockpile grids fail with a clear range error if their dimensions are inconsistent; valid input renders and computes as before.
color-pickerempty-stategroundwork-backgroundmarketplace-mapopportunitiesroute-mapscope-pickerstockpile-visualiseruk-material-networkvehicle-registration - Fixed#90
File trees retain a keyboard entry point when data arrives after initial render, and speech recording preserves the browser's actual audio format. Environment exports preserve literal shell characters and reject invalid variable names; code blocks use higher-contrast syntax colours in both themes.
ai-file-treeai-speech-inputai-environment-variablesai-code-block - Added#90
Adds 21 AI Elements for agent activity, structured results, attachments, speech and audio controls, and interactive prompts. Each has a fixture-backed showcase route. The file tree supports keyboard navigation with one tab stop; microphone and speech controls expose permission errors, audio controls wrap within mobile widths, and Persona follows reduced-motion changes.
ai-agentai-attachmentsai-audio-playerai-commitai-environment-variablesai-file-treeai-jsx-previewai-mic-selectorai-package-infoai-personaai-questionai-sandboxai-schema-displayai-snippetai-speech-inputai-stack-traceai-suggestionai-terminalai-test-resultsai-transcriptionai-voice-selector - Fixed#90
Voice selection updates the selected value and closes its dialog. Speech controls preserve caller click handlers and their internal availability checks; attachment removal stays visible on keyboard focus, and Persona honours an explicit light theme ahead of the operating-system preference.
ai-voice-selectorai-personaai-speech-inputai-attachments
- Added#89
`opportunities` no longer fixes its words or its certainty: a consumer can supply its own vocabulary and its own cost ranges, and leave out what it does not hold. Existing data and props render exactly as before. Labels. Wrap a surface in `<OpportunityLabelsProvider labels={…}>`, or pass `labels` to any one component, with a partial `OpportunityLabelsInput`: the tables `verdicts`, `strategies`, `timingFits`, `statuses`, `routeNodes`, `costKinds`, `scoreTiers`, `materialRelations`, `conditionStatuses` and `complianceStatuses`, and `phrases` for every heading, caption, empty state and accessible name (values are filled into `{token}` placeholders). It is plain data merged over `DEFAULT_OPPORTUNITY_LABELS`, so a server module can declare it. A vocabulary of a different size maps onto the existing keys rather than widening them: relabel the verdict key that behaves the way yours should, re-tone it with `verdictTones` (`positive`, `caution`, `doubtful`, `negative`, `undecided`) and list only the keys you use in `legendVerdicts`; strategy keys carry nothing but a label, and `strategyLabel` on an opportunity covers a strategy no key fits. Ranges. A cost line takes `range: { low, high }` around its likely `amount`. `opportunityTotalCostRange` and `savingsRangeVsBaseline` derive totals and savings as low / likely / high (the low saving pairs the dearest alternative with the cheapest baseline), and the bounds are drawn wherever the cost is: beside the figure in cards, tables and the detail, as a whisker under the cost bar and through decision-grid dots, and as a band on the baseline line and on flow ribbons. Ordering breaks ties on the bounds, the comparison's cost tick turns grey where the cheapest option's range overlaps another's, and the decision grid's cost axis now reaches below £0 when a net credit takes a figure or a bound there. `data.ts` gains a third demo set, `CHALK_REQUIREMENT` and `CHALK_OPPORTUNITIES`, with ranged lines and the optional parts left out. Optional parts. `costs`, `timing`, `totalDistanceKm`, `status` and `viability.confidence` are now optional, alongside `compatibility` and a route node's `geo`. A pathway with no `costs` reads "Not costed" rather than £0, and matrix columns, comparison rows, badges and chart marks that nothing fills are not drawn; a set with no baseline no longer labels every pathway "Baseline route". Code of your own that reads those five fields must now allow for `undefined`. `cost-breakdown`, `route-pathway`, `viability-panel`, `opportunity-detail` and the badge atoms are now client components, because they read the labels from context; they still render from a server component with the same props. Re-install `opportunities` to pick it up: two files are new, `labels.ts` and `opportunity-labels-provider.tsx`.
- Fixed#88
`SidebarSeparator` now stays inside the sidebar column. The base separator's full-width rule (`data-horizontal:w-full`) outranked the wrapper's plain `w-auto`, so the line rendered at 100% width plus its margins, overflowing `SidebarContent` and giving every sidebar that used one a horizontal scrollbar (24px of it with a consumer margin such as `mx-3`); its margins now inset the line as intended, still 1px in the sidebar border colour. Re-install `sidebar` to pick it up, after which a call-site `data-horizontal:w-auto` workaround is redundant and can be dropped.
- Changed
Scope breadcrumbs, org switcher and user menu pick up the nx header project-switcher pattern: compact search, scrollable lists, a tick on the current item, and optional create/manage actions. Switcher menu labels sit inside `DropdownMenuGroup` so Base UI GroupLabel no longer throws when the org, project or account menus open. The live `/view/block-app-shell` example now dogfoods ScopeBreadcrumbs and UserMenu as ordinary product chrome (the demo Show/Hide details panel controls are gone from that view — the separate docked-panel demo on the App shell docs page remains). The App breadcrumbs gallery page redirects to Scope breadcrumbs; the installable `app-breadcrumbs` block for plain trails is unchanged.
- Changed#85
An organisation with no uploaded logo now falls back to a gradient mark derived from its organisation id, with its initials over the top, instead of the same brand-tinted initials for every organisation. Colours are stable across renames and match the mark nx-id serves for the same organisation, and both gradient stops clear WCAG AA against the white initials at every hue. `OrgAvatar` therefore needs `org.id` as well as `name` and `logoUrl`; an uploaded `logoUrl` still wins. The org-switcher showcase no longer hotlinks a third-party avatar API for its example logos.
- Changed
Simplified the workspace example with shorter navigation, consistent compact page headers and filters, clearer project cards and a focused daily overview. Material requirements and matches now put progress and next actions first; wider forms keep their save controls visible. Delivery planning opens as an agenda, tasks support explicit review outcomes, and evidence and site details use readable drawers. Reports show labelled delivery progress, activity is grouped by day, and team and preference screens explain their project scope.
- Fixed#80
Page-header text can shrink beside its actions, and actions can wrap on phones. CI now checks that the app shell stays within phone, intermediate and desktop widths while wide tables remain independently scrollable, with and without the top bar in both themes. Consumer guidance explains the width contract and targeted component provenance; the drift workflow now covers the current application family and monorepo roots.
- Added
Material selection combines visual browsing and familiar-name search with optional preparation, origin and specification details. Full-flow and compact-field components accept UMM data and artwork via props, preserve unknown answers, and keep requested properties separate from reported properties. Material Studio demonstrates both surfaces against the UMM service. An optional catalogue profile controls browse groups, searchable materials, familiar labels and artwork allocation. Material Studio uses the Nexus soils-and-aggregates profile, keeping crushed concrete and road planings discoverable under Aggregates while preserving canonical identities. Search promotes exact names and aliases before common choices and curated profile order, with stable ties. The Nexus profile puts common bulk soils, sub-base, crushed concrete and road planings first; these priorities match the profile API search ranking. V1 release-candidate contracts add material/use/specification entry routes, primary/recycled/secondary/blended origin filters, versioned reference selections and all-required/any-acceptable specification groups. A composable quantity input preserves stated amounts or dimension inputs, distinguishes volume and moisture basis, and supports explicit international units and sourced density estimates. Invalid amounts cannot be confirmed or exported. The new `material-selection.1-rc.1` payload replaces the prototype's singular specification answer; prototype hosts must adopt the structured group and quantity fields. Cross-unit conversions can opt into a reviewed UMM density reference only when the record has `reviewStatus: "reviewed-usable"`, `usableForConversion: true`, complete review provenance and matching material and physical/moisture bases. The conversion retains the reference id, revision, catalogue version, midpoint, range source and bases; manually entered densities remain marked unassessed, and no conversion is assumed when the current UMM release has no usable record.
- Fixed
`command-search` no longer offers results from a query the user has moved on from. Remote groups render with cmdk's filter switched off, so while the next query loaded, the previous query's rows stayed fully clickable — and reachable with Enter — and could navigate to a record that did not match what was on screen. Rendered remote results are now tied to the query that produced them: the moment the two differ — from the keystroke that supersedes them until their replacement lands — they are dimmed and marked disabled, which is what makes cmdk skip them for both pointer and keyboard selection. Re-issuing the *same* query is unaffected, so a retry or a change of `search` function identity still keeps its rows live and the list does not flicker. A changed `searchKey` continues to clear the results outright. Consumers need do nothing; if you vendored the block before this entry, re-install it.
- Added#81
`command-search` is a new block: a ⌘K command palette with an app-shell trigger, built to be vendored into any React app. It imports nothing from `next/*` and assumes no router — a row with an `href` goes through `onNavigate(href, item)`, which defaults to `window.location.assign`, and a row may carry its own `onSelect` instead. Nothing touches `window`, `localStorage` or `navigator` during render, so it renders on a server; the trigger's shortcut hint resolves the platform modifier in an effect after mount rather than mismatching hydration. Results compose from three sources. `staticGroups` are always-available pages and actions filtered in the browser. `search` is an async callback for remote hits, debounced (`debounceMs`, default 150) past `minQueryLength` (default 2), handed an `AbortSignal`, and guarded so a response that arrives after a newer request is discarded rather than rendered. While a remote query is live, cmdk's own filter is switched off so server hits are never second-guessed, and the static groups are filtered locally instead. `recents` persists chosen rows to `localStorage`, but only the ones a consumer-supplied `filter` accepts — that gate is how a product keeps personal data out of the browser store — and every read and write is wrapped so a blocked or full store just means no recents. Remote results never outlive the context they answered in. `searchKey` names that context — an organisation id, an account id, a data-version stamp — and changing it while the palette is open retires anything in flight, clears the rendered remote results and runs the current query again. Changing the `search` function's identity retires the in-flight request as well, so a response from the previous fetcher can never be applied; results already on screen are kept, which means an inline arrow recreated by a parent re-render costs a re-issued request rather than a flicker. Recents are held to the same standard in the other direction: `onSelect` does not survive serialisation, so a callback-only row is persisted only when a current `staticGroups` item shares its id (it is re-linked to that live item on the way back out, callback and icon intact), and an entry that could only return inert is never written — and is dropped on read if an older one lingers. States cover idle, loading (skeleton rows, with any previous results kept on screen), results, empty and error-with-retry; the result count is announced through a polite live region, the dialog carries a name and description for screen readers, and focus returns to whatever opened the palette. `hotkey` accepts a descriptor such as `"mod+k"` (the default) or `"/"`, ignores an unmodified shortcut while someone is typing in a field, and takes `false` to disable the binding entirely.
- Added
Expanded the Nexus workspace example with connected material requirements and detail views, match comparison, delivery planning, tasks and approvals, evidence, sites, reports and activity. Organisation and project selection filter shared example data throughout. Changes update the local demonstration and reset on reload.
- Added
Added a complete Nexus workspace example combining the app launcher, organisation and project scope, connected operational pages and dockable movement details. Find it in the full examples gallery; all data and settings changes are local demonstrations.
- Added
Adds composable UMM material selection, reference-detail and density-estimate blocks. Consumers provide their own versioned catalogue data; selections and estimates do not make compliance, waste-status or suitability claims.
- Added
Added controlled hierarchy-aware organisation scope controls for group, region and operating-company views. Consumers supply authorised directory nodes or paginated search/children callbacks, while the picker keeps expansion, ancestry search, retries and focus local and leaves identity/session policy with the product.
scope-pickerorganisation-scope-breadcrumbs - Fixed
Fixed vertical lifecycle steps so connectors and row spacing remain visible when a step has no description. Horizontal steppers now use equal-width columns with markers centred over their labels and connectors spanning the space between markers, including clickable movement timelines.
- Added
Added a full material-requirements example with import and export capture, searchable records and companion detail views. Optional specifications, logistics, budgeted rates and supporting-file references can be added later; example edits persist in the browser.
- Docs#69
The living material network simulation now has its own showcase at `/patterns/material-network`, separate from the living background studies. Registry links point to the new page; the component and its API are unchanged.
uk-material-network The registry and showcase now use the latest stable dependency set, including Next.js 16.3, React 19.3, TypeScript 7, Base UI 1.8, Recharts 3.10.1 and TanStack Table 9. Reinstall the affected items to receive their refreshed npm requirements; `data-table` now uses TanStack's v9 logical `start`/`end` pinning positions instead of physical `left`/`right`. Consumer tables and PDF-template routes should follow [the 0.2 migration guide](https://github.com/nexus-regen/nx-ui/blob/main/docs/dependency-migration-0.2.md) before updating their locks. `versions.json` hashes now cover source, install targets and declared npm/registry dependencies. Run `bun lib/nx-ui-doctor.ts lock` once after updating so existing consumer locks record the new install-contract hashes; future dependency-only releases will be reported as drift.
accordionai-canvasai-code-blockai-connectionai-controlsai-edgeai-messageai-nodeai-panelai-prompt-inputai-reasoningai-shimmerai-toolbaralert-dialogattachmentavatarbadgeboundary-mapbreadcrumbbubblebuttonbutton-groupchartcheckboxcheckbox-cardcheckbox-groupcollapsiblecolor-pickercomboboxcontext-menudata-tabledate-pickerdialogdrawerdropdown-menuhover-cardinputinput-otpisochrone-toolitemlistings-panellocation-selectorlucide-providermap-markermap-toolbarmap-viewmarkermarketplace-mapmenubarmessage-scrollermotionnavigation-menunotification-centrenumber-inputpdf-templatespopoverprogressradio-groupresizableroute-maproute-toolscroll-areaselectseparatorsheetsidebarsite-mapslidersonnerstockpile-visualiserswitchtabstestimonialstoggletoggle-grouptooltiptransfer-previewtreeuse-listings-clustersuse-marketplaceutils- Added
Add an opt-in Cut Forms app-icon family with seven refined identities, four hypothetical extensions, six complete palettes and optical variants for small sizes. Exchange retains its yellow tile across palettes; the showcase includes contextual previews, downloadable assets and a documented design/prompt workflow. Existing app icons and app-directory defaults are unchanged.
nx-cut-form-iconnx-cut-forms - Changed
AppSwitcher now opens a compact, anchored and non-modal app menu with an icon-only grid trigger by default. Consumers can opt into the labelled sidebar trigger or a compact list layout with descriptions; larger directories gain search and a bounded scrolling body while active, coming-soon, locked and unavailable states keep their existing link behaviour.
- Fixed#72
Multiple canvases on one page now receive distinct React Flow accessibility IDs. An explicit consumer-supplied canvas ID still takes precedence.
ai-canvas - Fixed
Primary and destructive buttons gain a subtle top inner edge in both colour modes, while `--font-body` now aliases the shared sans font. Secondary buttons retain their existing input border so dark-mode contrast and joined control edges remain stable.
buttontheme - Added#69
AppShell now supports opt-in desktop sidebar resizing with keyboard controls and optional width persistence. An optional aside sits beside the page card inside the shell gutter; contentHidden hides the page card while retaining the header and mounted content. Existing shells keep their current layout unless these features are enabled.
app-shellapp-shell-resize
- Changed
User Menu groups light, dark and system choices into one compact, icon-only row with accessible labels and makes large organisation lists searchable and scrollable. Optional `accountHref` and `onCreateOrg` props add an environment-specific account-portal link and a New organisation action; existing callers remain supported. The current organisation appears first when browsing, with clearer selected states. Search shows matching counts and a quick clear action, while icon-only appearance controls keep accessible names and hover labels.
- Added
An alternative icon-only app launcher opens a spacious, searchable Nexus app directory with branded cards, current-app context and clear unavailable states. The new app-launcher example pairs it with an Assurance-style logo and search header; the existing compact app-switcher remains available.
- ChangedBreaking
nx-id is now the source of truth for the app catalogue (nx-standards ADR-021) and nx-ui renders it: `nx-apps` v3 adds `fetchNxApps({ issuer, headers, orgId })` over `GET /api/auth/nexus/apps`, the wire types (`NxCatalogueApp`, `NxCatalogueResponse`, `NxAppState`), and `toSwitcherApps(apps, activeId)`; `NX_APPS` becomes the snapshot fallback `NX_APPS_SNAPSHOT` and `resolveNxApps` is deprecated but unchanged. `nx-app-icon` accepts a custom tone (`{ bg, bg2?, fg, ring? }`) and mark (`{ viewBox, d, evenodd? }`) and degrades unknown names to `navy`/`emblem`, and the new `nx-app-card` block renders the large and compact launcher cards with their pattern field, hero asset, and locked/upsell/coming-soon states. Three fallback and rendering details worth knowing: `snapshotSwitcherApps()` with no user now returns the customer-audience apps only (pass a user and it enforces the audience/entitlement policy), so an unresolved shell no longer advertises the internal tools; the snapshot drops the hrefs of `files` and `sim`, whose only host is a development origin, leaving `email-hub` as the documented `.dev` exception; and `NxAppCard` hero assets switch on the app's own theme class rather than the OS colour scheme, behind a legibility scrim. **Breaking:** the Materials Exchange id is now `mep` (nx-id's registered entitlement key; "materials-exchange" stays in its keywords). Consumers passing `activeId: "materials-exchange"` must change it to `"mep"`. Move from `resolveNxApps` to `fetchNxApps` + `toSwitcherApps`, with `snapshotSwitcherApps(activeId)` as the fallback when the fetch fails. The catalogue is still never a security boundary — every app gates its own auth.
- Fixed
Wide content (data tables, example ledgers) no longer stretches the app shell past the viewport. `SidebarInset` and the page card now shrink with `min-w-0`, so leftover width is the space beside the sidebar, and tables scroll horizontally inside their own frame instead of pushing the page sideways.
- Added
Adds a synthetic UK material-exchange background with seeded site lifecycles, capacity-reserved loads, fulfilment, fair-share dispatch and a scrub-friendly timeline. Terrain surveys now evolve by default; 3D studies are anchored unless bobbing is enabled, with an edge-to-edge field option, more generation/style controls and 27 showcase presets across the seven studies. All automatic motion respects reduced-motion preferences; the UK network is illustrative, not a road-routing model or validated forecast.
- Added
Added transparent contour and ribbon SVG backgrounds with adjustable cycle length, travel, density, scale and intensity. Both support static rendering, pause/resume and automatic reduced-motion fallbacks; the new Living backgrounds playground demonstrates them alongside four generated texture studies.
- Added
Added four procedural SVG backgrounds: natural terrain contours, a terraced cut-and-fill model, a triangulated ground scan and a connected construction-site network. Seed, ruggedness, relief, viewing angle, excavation datum and connection controls shape the appropriate models; each supports pause, static rendering and reduced motion. The Living backgrounds playground now compares six directions with adjustable surfaces and composition.
groundwork-background - Docs
Consumer guidance and agent manifests now link to nx-id’s supported integration profiles and central account portal. Organisation selection is app/tab-local, with validated scope hints, current backend checks and confirmed logout; this supersedes the earlier shared/account-level scope guidance (consumer skill 2.0). Component APIs, styles and registry content are unchanged.
- Added
Backgrounds now support stronger travel and a speed multiplier. The groundwork kit adds a reusable motion controller for looping orbit, terrain-emergence and excavation tours, plus damped hover/drag interaction with keyboard alternatives; pause, static mode and reduced motion take priority. Scan sweeps, reference grids, markers, shading, excavation hatching, datum planes, routes and material signals can be toggled independently in the playground.
living-backgroundgroundwork-background - Changed
Backdrop defaults and named presets no longer draw vertical blueprint side rails or corner ticks, leaving the patterns, glow and grain unobstructed. Explicit `config={{ frame: true }}` remains available for consumers who want the frame.
- ChangedBreaking
`sidebar-nav` no longer imports `next/link` — the only Next dependency left anywhere in the registry, and the reason the build failed outright for every non-Next consumer. Items with an `href` now render a plain `<a href>`, and a new optional `renderLink` prop supplies a router link instead, forwarded by `scoped-nav` to both of its levels. **Migration for Next.js (and any router-driven) consumers: pass `renderLink={({ href }) => <Link href={href} />}` to `SidebarNav`/`ScopedNav` — it typechecks and looks identical without it, but every nav click becomes a full document load, losing prefetch, scroll restoration and in-memory SPA state.** React Router is `({ href }) => <Link to={href} />`. `href` and `onSelect` are also no longer mutually exclusive, so an item can keep real link semantics — Cmd/Ctrl-click, middle-click, open-in-new-tab — instead of degrading to a button. Where the two are combined, `onSelect` is skipped for modifier and non-primary clicks, which previously navigated the current tab as well as opening the new one; on an ordinary click the link still navigates itself, so a combined `onSelect` is a side-effect hook (close the mobile sidebar, telemetry) rather than a routing hook — **if you previously combined `href` with an `onSelect` that routed, move the routing to `renderLink` or drop the `href`**. An item with neither `href` nor `onSelect` used to render `<a href="#">`; items with no `href` now render a real `<button>`, which also fixes sub-items whose `onSelect`-only rows were anchors with no `href` — unfocusable, and inert to keyboard users.
- Fixed
A round of fixes found by migrating a real non-Next consumer (a Vite + React 19 SPA) onto nx-ui — every one of them affects any consumer. (The `sidebar-nav`/`scoped-nav` half of that round is a separate, breaking entry.) `app-breadcrumbs` and `scope-breadcrumbs` skip a crumb's `onSelect` on modifier and non-primary clicks: an anchor paired with an `onSelect` previously navigated the current tab as well as opening the new one. `sidebar` closes an accessibility hole and three layout defects: an offcanvas-collapsed sidebar is now `visibility: hidden` rather than merely parked off-screen (its nav controls stayed focusable and in the accessibility tree, with `SidebarRail` opting back in so the sidebar can still be reopened); `SidebarContent` drops its hard-coded `no-scrollbar`, which left an over-tall nav scrollable with no affordance at all; `SidebarMenuAction` and `SidebarGroupAction` grow to 24x24 to meet WCAG 2.5.8 on pointer devices, where their touch halo is deliberately disabled; the menu-button's padding is split into `px-2 py-1.5` so it no longer dictates row height; and `SidebarGroupLabel` drops from `h-8` to `h-6` around its 16px line box. `avatar` fixes a contrast failure that showed on every screen of a consumer app: fallback initials were 2.18:1 in light and 1.36:1 in dark against WCAG AA's 4.5:1, and now use `text-fg-secondary` (8.84:1 / 7.10:1); the avatar-group "+N" chip took the same token. `sonner` restores the `next-themes` fallback (`resolvedTheme ?? theme ?? "system"`) that stopped a light-themed toast flash before hydration, and `data-table`, `progress` and `tags-input` shed unused declarations that failed to typecheck in consumers running `noUnusedLocals` — sixteen other shipped files still trip that flag and are listed under Troubleshooting in `docs/registry.md` pending a follow-up. `nx-ui-doctor` finally works outside a repo-root layout: it reads `aliases` from `components.json` and resolves them through the project's `tsconfig`/`jsconfig` path mapping (following `extends` and project references, so Vite's split config resolves), so `wrap-audit` no longer reports every vendored file as missing in a `src/`-layout repo — local-edit detection had never once run there.
- Added
nx-ui now officially supports `lucide-react` alongside `@untitledui/icons` in consumer app code. Both sets draw on a 24 viewBox at stroke-width 2 with round caps and joins, so they interoperate without adjustment. The new `lucide-provider` item pins that weight against a future change to lucide's default, and any individual icon can still override it with a `strokeWidth` prop or a `stroke-[…]` utility.
- Docs
Close the agent-facing documentation gap in `llms.txt` / `llms-full.txt` / `llms/`. Both manifests resolved an item's docs page by nav slug alone, which silently missed every section-prefixed item (`ai-conversation` lives at `/ai/conversation`), picked the wrong page when two sections share a slug (`message` linked to the AI page, `opportunities` to the empty full-screen preview), and had no answer for pieces demonstrated on a shared family page. A new shared resolver, `scripts/showcase-pages.ts`, matches on nav slug, then route key, then attribution to a page that imports the item — lifting per-item demo coverage from 170/232 to 203/232, with the family-page snippets labelled as such. The API extractor also learned the `const X: SomeComponentType = (props) => …` style, so props typed on the variable rather than the parameter are no longer dropped. Adds a `Toolbar` demo to the workflow page, the one AI part that was shipped but never shown.
ai-canvasai-connectionai-controlsai-edgeai-nodeai-panelai-toolbarisochrone-toolmessageopportunitiesroute-tool - Fixed
`featured-icon` no longer crashes when given a `lucide-react` icon — and nor do `metric-card` and `empty-state`, which pass their `icon` prop straight through to it. lucide icons are `forwardRef` objects rather than functions, so the old component-vs-element check misread them as a React child and React threw "Objects are not valid as a React child". Reinstall `featured-icon` if you pass icons from any set other than `@untitledui/icons`.
- Fixed#57
Tidied the layout and alignment across the auth and account surfaces. `account-settings` no longer renders an empty padded band above the first row when there is no action notice, its list sections use a single full-width row idiom (leading mark, title/meta, actions pinned right) instead of the label-left settings grid, and the success notice uses the utility palette rather than undefined `success` classes. `auth-signup`'s terms checkbox label no longer breaks apart onto four lines (the shared `Label` is a flex container), and the strength meter shows a visible track with an inline strength label and neutral, non-alarming markers for unmet requirements. `auth-login` link buttons drop the `sm` size that was inflating the password-label row, icon-only social buttons gained accessible names, the brand panel pins its logo to the top, and `AuthCenteredLayout` recolours the field-separator chip so it matches the card in dark mode. `auth-recovery` gives every step the same header mark, centres the OTP group, and generates unique field ids. `credentials` cards align their empty states with the account blocks, stop wrapping the `x-api-key` code span, and generate unique create-form ids. The `/view/sign-in`, `/view/sign-up` and `/view/forgot-password` examples now compose these blocks instead of duplicating the forms.
- Added
Added `pdf-templates`, an installable set of renderer-native, monochrome A4 documents powered by the Takumi renderer used by PDFCN: an invoice, an operations report, and an evidence-led compliance certificate. The block exports serialisable data contracts, printable document components, deterministic samples, and `renderPdfTemplate()` for use in a consumer’s server route, worker, or job.
- Added
Nexus Account now appears in the canonical app directory as a live customer portal at myaccount.nexusregen.com, with a profile/security-focused descriptor and search terms. The app-icon family gains a dedicated user mark so account surfaces are recognisable in every shared app switcher.
nx-app-iconnx-apps - Added
Add account-management sections for identity consumers: profile presentation, linked sign-in methods, passkeys, sessions and organisation memberships, including reusable loading, empty, feedback and destructive-confirmation states. Every component takes display data and callbacks only, so applications retain their own nx-id integration, authorization and lifecycle policy.
- Added
New **`credentials`** block: the account-credentials kit for self-serve portals (NX-776). `ApiKeysCard` manages a user's central API keys — create form (name + expiry in days, bounded to the server's policy), a shown-once secret panel with copy button and warning copy, a list with `start` prefix/created/expiry/last-used, and revoke behind a destructive confirm. `ConnectedAppsCard` lists OAuth consents (client name/host, scope badges, grant date) with the same revoke-with-confirm idiom. Both are data-driven like every nx-ui block: the consumer owns the data and supplies async callbacks (Better Auth `apiKeyClient` create/list/delete and the oauth-provider consent endpoints — wired in nx-myaccount); the blocks own only the interaction states and render thrown callback errors inline.
- Changed
Geo joins the family: the `nx-apps` directory gains Nexus Geo (geo.nexusregen.com — internal geo-services and HGV routing platform), and `NxAppIcon` gains the `pin` mark for it — a map pin with the hole knocked out, on the graphite tile. The switcher grid is now six apps in two rows; Nexus Geo itself adopts the AppSwitcher in its shell this round, so the family is fully linked across agent-services, emailhub and geo.
nx-app-iconnx-apps - Changed
AppSwitcher v2, built for the unified cross-app shell rolling out across the Nexus family (Agent Services and Email Hub first). The popover grid is now choreographed — tiles stagger in on springs, hover lifts and press sinks, the active app's tick pops in and the trigger chevron flips (all instant under `prefers-reduced-motion`). Past six apps the popover gains a filter matching name/description/keywords with ArrowDown into the grid; a `statusBadge` field marks beta apps; a `footer` slot takes an environment hint or directory link; and an `onSelect` callback fires before cross-app navigation (telemetry hook). New `enabled: false` app state renders a locked, non-followable tile ("No access") — the visible-but-disabled shape entitlement gating needs. New **`nx-apps`** module: the canonical directory of Nexus apps (`NX_APPS`) plus `resolveNxApps({ activeId, user })`, which applies the access policy ahead of the billing/entitlements work — `audience: "staff"` apps hide from known non-staff users, `entitlement`-gated apps render locked without the entitlement (staff bypass), and with no user passed everything fails open since apps gate their own auth. Adding an app to the family is now one directory entry and a re-vendor, instead of editing every consumer's shell. Also in this round: standalone `lib/*` registry items no longer pin an explicit install `target`, so they land through each consumer's `lib` alias (repo-root `lib/` or `src/lib/`) like `utils` always has — an explicit target bypassed the alias and stranded the file where `@/lib/<name>` couldn't resolve it. Consumers with a previously-installed lib item (mapbox, nx-ui-doctor, …) may see one drift flag; content is unchanged, so `--overwrite` or re-`lock` clears it.
app-switchernx-apps - Changed
Per-app identities: `NxAppIcon` gains a `mark` prop — named identity glyphs (`shield`, `bolt`, `mail`, `exchange`, `sliders`) drawn as single-colour fills in the tile canvas, replacing the one-arrow-fits-all emblem in the app switcher grid. The Nexus arrow stays the default (`mark="emblem"`), so existing tiles are unchanged; `AppSwitcherApp.mark` carries it through the switcher trigger and tiles. Directory refresh in `nx-apps`: Materials Exchange is live at use.nexusregen.com, Manage (the MEP admin panel) joins at manage.nexusregen.com, Agent Services now lands on `/admin` (its apex is the public docs surface), and Procurement drops off until it's real. Access-policy default flip: `resolveNxApps` now renders the **same directory everywhere by default** — every app visible and enabled — because per-instance nx-id role differences made the switcher inconsistent between apps for the same user. The staff-audience / entitlement policy is unchanged but moves behind `enforceAccessPolicy: true`, to be switched on once roles and billing entitlements are reliably populated (ADR-016's billing-prep shape stands).
- Internal
Tooling & docs: a keyboard-interaction smoke test (`bun run smoke:keyboard`) drives arrow-key widgets (menubar, combobox, tabs, radiogroups, sliders…) and runs in PR CI; the a11y audit gains a warning budget (`A11Y_WARN_BUDGET`, ratcheted at the current 58 baseline in CI); a weekly `loop-consumer-drift` workflow runs `nx-ui-doctor check` in consumer repos and files drift issues (inert until `AGENT_LOOPS_ENABLED` + a `CONSUMER_REPOS_TOKEN` secret exist); the charts gallery gains a per-theme colours demo exercising `theme: { light, dark }`; and a small contrast sweep moves content-bearing text off `text-fg-quaternary` in the showcase chrome and example pages.
- Internal
Showcase & tooling: new gallery pages for data-table, scope, scope-breadcrumbs, nx-app-icon and nx-emblem; the API-reference extractor now covers all `ai-*` items and the nested block families (113 → 192 documented items); dependency chips link correctly for AI items; `[`/`]` keyboard paging through the gallery; the repo gains its first test suite (127 vitest tests over the lib modules and build-script parsers, `bun run test`); and PR CI now runs the interaction smoke test and a11y audit against a production build.
- Fixed
Item type corrections: `use-marketplace` and `use-listings-clusters` are now declared as `registry:hook`, and the types-only `marketplace-types` contract as `registry:lib` (all three were previously mislabeled `registry:block`). Install paths are unchanged.
marketplace-typesuse-marketplaceuse-listings-clusters - Added
Four new domain/marketplace atoms: `ewc-badge` (a compact EWC code chip with hazard asterisk and dot), `price-range` (the marketplace gate-fee range formatting as a standalone atom), `movement-status-badge` (per-status pills for the waste-movement lifecycle) and `movement-timeline` (the lifecycle as a stepper built on the ui Stepper, with timestamps, notes and clickable steps).
- Added
Two new domain components: `mass-input`, a weight/volume control (t / kg / m³) with a live density-converted equivalent readout when a material or density is given (built on `number-input` + `native-select`, densities from `data-material-terms`); and `transfer-document`, a duty-of-care waste transfer note preview surface (paper sheet, parties grid, EWC/quantity block, signature slots with an `onSign` callback) fed by the same values shape as `transfer-note`.
- Changed
The UUI component tokens are now actually consumed: Switch gains an optional `slim` variant (the UUI slim-toggle treatment, `slim` prop + `data-slim`), and the default Switch border, Slider handle and Avatar fallback now use their dedicated theme tokens (`toggle-border`, `slider-handle-*`, `avatar-styles-bg-neutral`) instead of generic shadcn classes. Also fixes the dark-mode value of `--color-avatar-styles-bg-neutral`, which stayed light-gray and produced light-on-light initials (now neutral-700). Light-mode visuals are unchanged except a hairline switch border and a slightly darker avatar fallback — both per the UUI spec; dark-mode slider handles invert to the spec's accent fill.
- Fixed
Three silently-broken styles fixed: the missing `--color-bg-secondary_subtle` token is defined again (data-table header/footer/pinned-column backgrounds were rendering transparent), the signup password-strength meter and requirement ticks now use real theme colours (the `success-*`/`warning-*` classes it referenced never existed), and per-theme chart colours (`theme: { light, dark }` in a chart config) now actually apply in dark mode — the emitted selector targeted `.dark` instead of `.dark-mode`.
- Internal
Brand variants now alias base ramps with `var(--color-*)` instead of duplicating hex literals (ocean brand → blue ramp, graphite accent → neutral ramp, accent = brand for ocean/ultraviolet/ember). Computed colours are identical — no visual change — and the variant-authoring rules (alias, don't copy; the five-variable dark-flip contract) are now documented in `docs/architecture.md`.
theme-oceantheme-ultraviolettheme-embertheme-graphite - Fixed
Accessibility round: the number-input steppers now show a visible focus ring; the interactive Rating is a real radiogroup (roving tabindex, arrow/Home/End keys); the settings nav marks its active section with `aria-current`; MenubarItem shows a pointer cursor; the toaster follows the app's resolved theme instead of the raw `system` setting; and every focus ring in the library now uses the same 24% ring tint (ring-4 for controls, ring-2 for small inline targets — the rule is documented in `docs/architecture.md`). The base theme also gains a blanket reduced-motion guard and a forced-colours (Windows High Contrast) block so focus stays visible when box-shadow rings are stripped.
- Added
Version management and agent ops landed: every registry item now has a published content hash in `/r/versions.json` (compare against your `nx-ui.lock` to detect drift), this changelog (one entry per PR, browsable at `/changelog`, machine-readable at `/llms-changelog.txt`), the `@nx-ui/nx-ui-doctor` script for consumer-side `lock`/`check`/`wrap-audit`, an agent onboarding page at `/agents`, CI, and scheduled maintenance loops.
nx-ui-doctor - Added#39
The `stockpile-visualiser` domain block: an interactive 3D soil-stockpile visualisation on a dependency-free canvas engine — a rotatable surveyed heightfield with test-location pins, live morph-animated stock levels, and geotechnical overlays for angle-of-repose stability, height compliance, test coverage, cut/fill deltas and cross-sections.
- Added#40
The haulage kit: `haulage-vehicle-select` (a UK construction/waste vehicle picker with drawn side-profile artwork, payload/volume/CO2e details and loads-required estimates, backed by the `data-haulage-vehicles` dataset) and `vehicle-registration-input` (a UK number-plate field that auto-formats all five registration formats, with a plate visual variant and live format/age/region decoding via the `vehicle-registration` lib module).
- Docs#35
The docs engine: view-code toggles on every demo, generated API/props tables, cross-link chips between related items, per-item markdown cards at `/llms/<name>.md`, a table-of-contents rail and dual-mode preview canvases.
- Docs
Docs-drift audit fixes: updated brand-variant docs to list all eight drop-in themes (added nexus-midnight, nexus-sand, nexus-slate which shipped without docs); corrected block install-path docs to reflect that all blocks install under `components/blocks/` (no flatten-to-root); filled out AGENTS.md structure table with three missing block subdirs (calendar-view, kanban, settings) and geo-fixtures dataset; fixed `registry.json` homepage to `https://ui.nexusregen.com` per architecture.md; added an icon name quick-reference table to the consumer skill.
- Fixed
Accessibility wave: all 111 serious findings from the a11y audit cleared across the component suite and showcase — missing accessible names and labels, aria reference integrity, duplicate ids, landmarks and contrast.
- Internal#34
Showcase wayfinding: collapsible nav groups, command-palette upgrades (including recents), a top bar dogfooding ScopeBreadcrumbs, a keyboard-shortcuts dialog, and the first changelog page.
- Fixed#30
Bare `text-tertiary`/`text-quaternary` utilities (which don't exist in the theme) replaced with the correct full-token forms `text-text-tertiary`/`text-text-quaternary` wherever they had crept in.
- Docs#12
Consumer skill bumped to 1.2.0: theme-variant wiring, block install paths and refreshed inventories.
- Added#27
Sidebar-nav scroll affordances via the new `scroll-fade` block, a user-menu organisation section, and breadcrumb Untitled UI parity.
- Fixed#18
Restored the shadcn custom variants and utilities the theme had dropped — `styles/shadcn-compat.css` now ships with the theme item, carrying the `data-*` variants and scroll/shimmer utilities the base-vega components rely on.
theme - Added#19
The scoped app shell for core nx products: optional top bar, org ▸ project scope breadcrumbs with switchers, the two-level sliding sidebar nav, and the app-switcher launcher. `app-shell` gained the top-bar slot (additive).
- Internal#32
Showcase QA tooling: live-preview viewport presets, the `/foundations/theme-matrix` page for eyeballing every brand x mode combination, and a generated design-token reference (`build-token-docs.ts`).
- Internal#14
Showcase preview UX: nav affordances, pointer cursors, and full-width + windowed preview modes.
- Added#31
Three visual-first opportunity surfaces: the proximity map, the cost-proportional flow canvas and the cost-vs-readiness decision grid.
- Added#29
The opportunity matrix family: pathway comparison cards, the options matrix and AI viability surfaces for material-routing decisions.
- Fixed#16
Notification centre rebuilt on the nexus4 anatomy: unread edge bars, severity tiles, date-grouped rows under sticky headers, inline decisions and hover quick actions.
- Internal#11
Motion and polish pass across the showcase — scroll reveals, transitions and consistency fixes.
- Added#24
The componentised marketplace map experience: supercluster bubbles with type-mix rings, the virtualised listings panel, the faceted filter panel, shared listing cards, and the headless orchestrator hooks.
marketplace-maplistings-panellistings-filterslisting-cardmarketplace-typesuse-marketplaceuse-listings-clusters - Added#6
The marketing pattern family: config-driven backdrops, heroes, section primitives, feature rows and cards, CTA band, logo cloud, testimonials, stats band, how-it-works, FAQ, and the site header/footer.
- Added#20
Map tooling: the glass-pill map toolbar, travel-time isochrone overlays, click-to-add waypoint routing (both against the nx-geo contracts), and the cinematic transfer-preview choreography.
- Internal#15
Site header/footer demos now use the real Nexus lockup; the footer watermark reuses `nx-emblem`.
- Docs#33
Home page redesigned (hero band, live registry stats, curated highlights) and a `/docs` section added to the showcase: getting-started, theming, components-and-blocks, app-shell-pattern and contributing guides.
- Internal#10
The examples gallery: full-page compositions served full-bleed at `/view/<slug>` — auth screens, dashboards, settings, error states and the live Movement Control Room.
- Added
DX wave: visual regression (`bun run visual`) and accessibility audit (`bun run a11y`) suites, generated per-component API docs on showcase pages, the `llms.txt`/`llms-full.txt` agent manifests, and the compact density mode (showcase-only theme capability).
- Added#17
Domain modal selector flows: the full EWC List of Wastes lookup modal, the grouped material picker modal with cascading suggestions, and the location field flow with directory search and a map escape hatch.
- Added#9
The TanStack Table data-table kit in the shadcn idiom: sorting, faceted and multi-column filters, global search, row selection with a bulk-action bar, pagination, column visibility and pinning, expandable sub-rows, loading skeletons and empty states — plus tables and charts showcase sections.
- Added
21 new components and blocks in one wave, a brand refresh, and the surface brand-variant themes (ultraviolet, evergreen, ocean, ember, graphite) switched by `data-brand`.
- Added#28
Collapsible open/close motion, the checkbox-card and checkbox-group components, and an accordion badge-gap fix.
- Added#13
The brand icon system: `nx-emblem` weights (regular keyline through solid), the Google-style `nx-app-icon` product family, and the yellow-on-dark logo treatment.
- Fixed#26
Glow variants, a brand-fill contrast audit across both modes, and the background-pattern stacking contract.
- Added#8
31 AI Elements ports (`ai-*` items: conversation, message, reasoning, tool, prompt-input, workflow canvas and friends), restyled to the nx look and installing to `components/ai/`.
- Added#4
The Mapbox map suite: a theme-aware `map-view` wrapper plus branded markers, clustered site maps, route maps with progress overlays, boundary polygons and glass stat overlays.
- Added#3
Untitled UI parity wave for forms: date picker, filters, tags, file upload, stepper and friends joined the suite.
- Added#7
The Nexus domain family: EWC (European Waste Catalogue) selector, construction material selector, UK location selector, project-scope selector and compliance checklist, with their reference datasets shipped as `data-*` items.
- Added#5
Untitled UI parity wave for display components, plus the design-flare utilities (`flare-styles`).
- Added
The two-layer design-token foundation landed: the full Untitled UI colour/type/shadow/radius system carrying Nexus navy and Aureolin yellow, mapped onto shadcn's semantic CSS variables, with light and dark driven by `light-mode`/`dark-mode` classes (primary flips navy→yellow in dark).
theme - Internal
Showcase gallery infrastructure and 69 demo pages (59 components + 10 blocks), dogfooding the app-shell blocks as the gallery's own chrome.
- Added
All 60 base components restyled to the Untitled UI look under the minimal-diff doctrine (tokens first, class deltas second, APIs untouched), plus the first 10 app-shell blocks and the registry build system that derives dependencies by parsing imports.
- Internal#2
Showcase preview UX: ⌘K search, brand theme variations behind a picker, and the generated navigation manifest.
- Fixed
Base UI menu labels must sit inside a Group — fixed everywhere and guarded by a new headless interaction smoke test (`bun run smoke`) that clicks every control on every showcase page.
- Internal
Repo scaffolded: Next.js 16 App Router showcase app with the full shadcn base-vega baseline (60 unmodified components) on Base UI primitives, Bun and Tailwind CSS v4.
- Fixed
Removed stale per-component `dark:` overrides that fought the theme's token flip — dark mode now comes entirely from CSS variables.
- Fixed
First consumption-test findings fixed: `shadcn init` guidance, removal of conflicting globals.css scaffolding, and correct consumer install paths for blocks.
- Docs
The two canonical agent skills shipped: `nx-ui-components` (consuming — discovery, install, theme wiring, troubleshooting) and `nx-ui-contribute` (maintaining — the minimal-diff doctrine and registry regeneration).