Skip to main content

Implementation Status

How much of the library is built, and how much each product uses. Per-product details are in the tabs; what is left to migrate, component by component, is on Migration.

How to read these numbers
Weighted usages:
Places in the code that still use MUI or @filigran/ui, July vs today.
Library readiness:
Share of those places whose library component is already built.
Components needed:
Library components a product uses or still needs to switch to.
Interface elements converted:
Rendered elements moved to the library, out of those it can replace today.
In service:
Library components a product imports and renders today.
Weight:
Places across products that a component will replace.

Layout wrappers (Box, Stack, Grid…) are not counted: they become styling utilities, not components.

Library — 52 components planned

43Done — built, verified, shipped
2In review — built, awaiting approval
0In progress — being built
7To do — not started

Ready for stable: Alert, Avatar, Badge, Banner, Breadcrumbs, Button, Card, CardContent, CardFooter, CardHeader, CardMetaBar, CardSubtitle, CardTitle, Checkbox, ColorPicker, Combobox, CustomizePanel, DatePicker, Dialog, Drawer, FileSelect, Header, Hero, HeroBody, HeroHeader, HeroStat, Input, Menu, Paper, ProgressBar, Radio, RichTextField, Select, Skeleton, Slider, Snackbar, Spinner, Textarea, Thumbnail, TimePicker — every accessibility check passes with no exemption. Promotion stays a human decision (pnpm promote:component <Name>).

Usage — the July scan against today

Legacy uses in July and today, per product. Readiness can fall while a product migrates: what is left then waits on components not built yet.

Weighted usageslegacy places a library component replaces
  • July scan, 2026-07-06
  • trunks, 2026-10-27
Show as a table
July 2026-07-06trunks, 2026-10-27
OpenCTI2,6532,298
OpenAEV9,3976,502
XTM CRQ3,023455
All products15,0739,255
Library readinessshare of those places whose component is built
  • July scan, 2026-07-06
  • trunks, 2026-10-27

Not a step back: OpenCTI went from 2,653 legacy places to 2,298 by moving what the library offers. 33.8% of what is left waits on components not built yet — List, DataTable, Accordion, Popover, Separator.

Not a step back: OpenAEV went from 9,397 legacy places to 6,502 by moving what the library offers. 35.0% of what is left waits on components not built yet — List, DataTable, Accordion, Popover, Separator.

Not a step back: XTM CRQ went from 3,023 legacy places to 455 by moving what the library offers. 65.1% of what is left waits on components not built yet — DataTable, Accordion, Popover, Separator.

Show as a table
July 2026-07-06trunks, 2026-10-27
OpenCTI71.3%66.2%
OpenAEV76.8%65.0%
XTM CRQ88.4%34.9%
All products78.2%63.8%

Rule: named imports from MUI (icons aside) or @filigran/ui, counted wherever the identifier appears in a front .ts/.tsx/.js/.jsx file. Replayed on the commits read on 2026-07-06, it reproduces process/mui-inventory.json entry for entry. Trunks read: OpenCTI master 5837b6928f · OpenAEV main 8b216f6454 · XTM CRQ main 028a52af4b.

Adoption across the products

Front-end component files (.tsx and .jsx), counted on the product repositories themselves, at three commits: the one before the design-system merge, the merge, and the trunk a user gets today. Generated code and tests are excluded from all three counts, so the percentages share one denominator.

ProductCommit readFront filesRendering the design systemStill importing MUI
OpenCTIbefore the design-system merge · c44d7ab8ab · 2026-09-082,1630 (0.0%)1,288 (59.5%)
OpenCTImerge of #18117 · 5b9bcf6116 · 2026-09-082,170304 (14.0%)1,232 (56.8%)
OpenCTImaster today · 5837b6928f · 2026-10-272,255355 (15.7%)1,274 (56.5%)
OpenAEVbefore the design-system merge · 262ffec23f · 2026-10-021,1350 (0.0%)866 (76.3%)
OpenAEVmerge of #7919 · 8ded09b623 · 2026-10-021,138550 (48.3%)743 (65.3%)
OpenAEVmain today · 8b216f6454 · 2026-10-271,136551 (48.5%)740 (65.1%)

Generated by pnpm scan:products, which reads each product repository read-only. A file counts as rendering the design system as soon as it imports it once — the count says how far the work has spread, never how much of a screen it paints. For that reading, see zone coverage in the product tabs.

Active workstreams

Everything currently claimed or moving in the component roadmap — who owns what, and where it stands. Weight = places across all three products that will use the component once migrated (see “How to read these numbers”).

PriorityComponentStatusOwnerPRWeight, July → today
1Buttondoneready for stable@fimow#1351,290 → 18
2Icondonesandy#12—
3Skeletondoneready for stablefimow#264135 → 230
3Tooltipdone@fimow#40930 → 298
4IconButtondone@fimow#135493 → 14
5Dialogdoneready for stablesandy#511,353 → 1,101
6Drawerdoneready for stablefimow#25660 → 33
7Alertdoneready for stablesandy#230279 → 381
7Snackbardoneready for stablesandy#2303 → 3
8Badgedoneready for stablesandy#215351 → 24
8Checkboxdoneready for stablesandy#7380 → 0
8FileSelectdoneready for stablethibault#157—
8Inputdoneready for stablesandy#2241,804 → 234
8Menudoneready for stablesandy#110979 → 405
8ProgressBardoneready for stablesandy#11819 → 22
8Radiodoneready for stablesandy#7344 → 0
8Selectdoneready for stablesandy#191646 → 0
8Sliderdoneready for stablesandy#789 → 6
8Spinnerdoneready for stablesandy#11532 → 34
8Switchdonesandy#13591 → 80
8Textareadoneready for stablesandy#17013 → 0
9Carddoneready for stablesandy#144365 → 217
9Comboboxdoneready for stablesandy#250117 → 10
10Chipdonesandy#192177 → 14
10Paperdoneready for stablesandy#121312 → 65
11Breadcrumbsdoneready for stablesandy#15217 → 0
11Herodoneready for stablesandy#232—
14Avatardoneready for stablefimow#25171 → 61
16ButtonGroupdonesandy#22991 → 107
17Typographydonesandy#441,753 → 2,469
18SearchFielddonesandy#189—
21Bannerdoneready for stablethibault#252—
23Headerdoneready for stablesandy#18930 → 29
24Navbardonesandy#107—
—ColorPickerdoneready for stable@fimow#173—
—CustomizePaneldoneready for stablesurbhi#247—
—DatePickerdoneready for stablesandy#24140 → 24
—HeroStatin reviewready for stablefimow#275—
—MarkdownFielddone@fimow#257—
—NavbarItemdonesandy#123—
—NavbarSubmenudonesandy#123—
—ProductSwitcherdonesandy#111—
—RichTextFieldin reviewready for stable@fimow#270—
—Tabsdonesandy#135191 → 27
—TimePickerdoneready for stablesandy#2417 → 3

Tracks

Axes not tied to a single component or product — release machinery, the visual-coherence harness, and other foundations work (process/FOUNDATIONS-REPORT.md §6, process/AI-BACKLOG.md).

TrackStatusOwner
check-figma-fidelity.ts hardening — verification of computed font-weightin reviewsandy
Missing mono Named Style in theme.cssto dothibault
Eradication of inline styles outside the system + CI gate (style={{}} blind spot in check:tokens)in progresssandy
Viewport safety net on the w-overlay-* utilities (single-subject fix)donesandy
Package entry ships every component's *.meta.ts — ~3x the runtime cost per componentto do—
Sync ROADMAP post-merges (#43 Navbar family, #44 Text) + desync catch-up (#40 Tooltip/IconButton, #41 SearchField) + batch evaluation of /status promotionsin progresssandy
S3 — Per-product consumer integration kitin progresssandy
S5 — Release machinery (npm publishing)in reviewolivier
S6 — Visual coherence harness (Playwright)in progresssandy
S8 — @filigran/ui deprecation plan (XTM CRQ)to do—
Scaffolding — contrastPairs checklist by state × variant + Rule 5 gatein reviewsandy
Spacing & color enforcement via the theme (lint as last resort)to do—

V2 / deferred — decided, not forgotten

Everything the project has deliberately pushed to a later version. Each entry says what it is, where its absence is felt today, what event retires it, and where the decision is written down. This is the one part of the page that is not generated: a deferral is a decision taken in a product’s feedback file, an RFC or an arbitration, and three of these do not exist in the roadmap at all — see lib/deferred.ts for why, and for the upkeep rule.

Sorted by reach today — occurrences summed across the three products, the same measure as “weighted usages” above, or sites counted by hand for a sub-feature. Reach is not urgency: an entry flagged blocking a migration today holds a dated exemption in a product’s own MUI guard, so a migration is held open right now whatever its count says.

  • Segmented control (ButtonGroup / ToggleButtonGroup)

    blocking a migration today107 usages across the products today, 91 in July

    A group of two or three buttons where exactly one is selected at a time — OpenCTI's search bar uses it to switch between advanced search, bulk search and natural-language search. The COMPONENT is no longer what is missing (see removalCondition): these are the call sites that have not converted yet.

    Where it is missing
    OpenAEV (73 today, 70 in July) — admin/components, components/common — ToggleButton + ToggleButtonGroupOpenCTI (34 today, 21 in July) — opencti-front/src/components/SearchInput.jsx — the top bar's mode toggles, plus ViewSwitchingButtons.tsx, dataGrid, fields
    Retires when
    HALF MET as of 2026-08-30, and the entry stays until the other half lands. The library half is DONE: ButtonGroup ships, owns exclusivity, roving focus and the selected style, and gained `asChild` in PR #193 (bd57527) so a segment can be a router link. What remains is the product half this condition also names — the OpenCTI header pilot deleting both survivors from TopBar.libraryOnly.test.ts's named list. Verified not done at origin/design-system/current: SearchInput.jsx still imports ToggleButton and ToggleButtonGroup from MUI for the bar's own mode toggles. Delete this entry when that import is gone, per the register's rule that an entry is removed when its condition is met and never marked done.
    Where it is written down
    OpenCTI fds-migration/LIBRARY-FEEDBACK.md #24, measured at pin 35a4768 — the last non-glyph MUI left in the bar, with the group's geometry and semantics measured so the component can be specified. CORRECTED 2026-08-30: this line used to end "ROADMAP.json tracks it as ButtonGroup (priority 16, todo)", which was true when written and is now false twice over — the component shipped and its ROADMAP row is `done` at PR #193. The entry is kept, and re-scoped above, because the sites it counts are still on MUI: OpenCTI adopted ButtonGroup in ViewSwitchingButtons.tsx (adoption `partial`), not in SearchInput.jsx.
  • Popover

    blocking a migration today37 usages across the products today, 37 in July

    A floating panel anchored to a control that holds arbitrary content — not a list of commands (that is Menu) and not a modal (that is Dialog). The library builds one internally to position Combobox, but does not export it.

    Where it is missing
    OpenAEV (24 today, 21 in July) — openaev-front/src/admin/components/nav/BulkOperationsIndicator.tsx — the bulk-operations panel, plus components/common and both colour pickersOpenCTI (3 today, 10 in July) — private/components — and the NLQ dropdown in the top bar, which MUI draws with oneXTM CRQ (10 today, 6 in July) — features/notifications, components/layout — on @filigran/ui
    Retires when
    Popover, PopoverTrigger and PopoverContent resolve from the built entry point. Both products then delete their dated exemption and their guard reddens until the panel is rebuilt — which is the point of having filed it that way.
    Where it is written down
    OpenAEV fds-migration/LIBRARY-FEEDBACK.md #22 (the only item still open there) and OpenCTI #24 “The Popover that comes with it”, exempted by Sandy on 2026-08-13. Verified at pin 35a4768 against the installed build, not a changelog: PR #105's primitive stays internal to Combobox. ROADMAP.json tracks it since 2026-10-27 (priority 4, todo), and process/mui-crosswalk.json maps MUI Popover and Popper onto it.
  • Separator (generic) — MUI Divider

    29 usages across the products today, 39 in July

    A standalone horizontal or vertical rule, usable anywhere. The library has three separators today — NavbarSeparator, MenuSeparator, SelectSeparator — and each is welded to its own component.

    Where it is missing
    OpenAEV (27 today, 29 in July) — admin/components, components/commonOpenCTI (2 today, 10 in July) — private/components
    Retires when
    A standalone Separator ships. Note that the case both pilots originally raised — the rule between a header's two action clusters — is ALREADY closed, by HeaderGroup separatorBefore (library PR #117): what remains deferred is the general-purpose component for the divider sites that are not header clusters.
    Where it is written down
    OpenCTI fds-migration/LIBRARY-FEEDBACK.md #18 and OpenAEV #22 (same ask, raised independently). ROADMAP.json (priority 20, todo, figmaDesigned: true); process/mui-crosswalk.json maps MUI Divider onto this entry.
  • Snackbar viewport — the Figma frame, not the behaviour

    2 sites, counted by hand

    Where a transient message appears on screen, how several stack, and how they enter and leave. RE-SCOPED 2026-09-19: the BEHAVIOUR now ships — Snackbar is built on @radix-ui/react-toast, with a provider, a portalled viewport placed 24px from the top and right of the window, a timer that pauses on hover and focus, swipe-to-dismiss and the F8 hotkey. What is still owed is the DESIGN: no Figma frame draws the viewport, so its placement (24px from the top and right) and its motion (a 220ms/160ms slide following MUI's Slide) are chosen values recorded in the RFC rather than read off a node.

    Where it is missing
    OpenCTI (1) — opencti-front/src/components/Message.tsx — the MUI Snackbar wrapper this now replaces; unblocked, not yet convertedOpenAEV (1) — openaev-front/src/components/Message.jsx — same wrapper, same state
    Retires when
    A Figma frame draws the viewport — placement, stacking order, entry and exit motion — and src/styles/motion.css is re-derived from it instead of from the defaults chosen here. The product half is no longer part of this condition: both wrappers can be deleted today, and when they are, that is ordinary migration progress rather than this entry's removal.
    Where it is written down
    Snackbar.rfc.md section 3.6 (Known Figma gaps) and section 4.6, which records the measurement behind the portal. SUPERSEDES the 2026-09-18 entry that deferred the behaviour itself: the design lead arbitrated on 2026-09-19 to take the Radix dependency in the same PR, so only the design gap survives.
  • ProgressBar buffer variant

    2 sites, counted by hand

    A second, paler bar behind the first, showing how much is loaded ahead of what has been processed — MUI's valueBuffer.

    Where it is missing
    OpenCTI (2) — the two upload dialogs — and both pass a “current + 10” placeholder rather than a real buffered value
    Retires when
    A design decision on what a second bar behind the first should look like, and at least one site with a real buffered value to justify it — today both sites would draw a fabricated number.
    Where it is written down
    ProgressBar.rfc.md §7 and Q10.
  • Indeterminate linear bar

    1 site, counted by hand

    The sliding stripe a progress bar shows when the work has no measurable percentage. Its circular twin already exists as Spinner; the linear one does not.

    Where it is missing
    OpenCTI (1) — GraphToolbar — the only indeterminate linear bar
    Retires when
    The sliding animation needs a new @keyframes in theme.css, which sits OUTSIDE the @utility zone agents may edit (AGENTS.md) — so this needs a token delivery from the Figma export pipeline, not a component change.
    Where it is written down
    ProgressBar.rfc.md §7 and Q6.
  • ProgressBar tone=“warning”

    no usage to migrate yet

    The orange status colour for a determinate progress bar, alongside the default, success and error tones that shipped.

    Where it is missing
    OpenAEV — admin/components/nav/BulkOperationsIndicator.tsx — nothing there needs warning today, but a fourth status would fall back to the default rather than borrow a neighbouring colour
    Retires when
    A token decision by Sandy. This is BLOCKED ON THE TOKENS, not on the component: --color-feedback-warning-primary (#e6700f) clears WCAG 1.4.11's 3:1 against no track token in theme.css in light mode — 2.51:1 even against its own 30% companion, the construction that carried success and error over the line. Shipping it would be a known accessibility failure, which AGENTS.md forbids outright.
    Where it is written down
    ProgressBar.rfc.md §7 and Q11/Q12 (measured, then re-measured); ROADMAP.json's ProgressBar notes record the escalation to Sandy.
Library progress, usage, readiness, adoption and the workstream tables are generated and never edited by hand. Data: ROADMAP.json (2026-11-04) × process/mui-inventory.json (static import + occurrence scan, 2026-07-06) × process/product-scan.json × process/mui-crosswalk.json. Regenerate: pnpm generate:artifacts — drift fails CI via pnpm check:artifacts. process/product-scan.json comes from pnpm scan:products, which reads the product repositories read-only and so runs next to their clones, not in CI. Zone coverage reads docs/lib/zone-coverage.json, a MEASURED artefact: a rendered-DOM bench reads the product repositories read-only and emits it, and pnpm check:zones recomputes its provenance hash so a hand edit turns the gate red. Two sources are maintained by hand because no generator can produce them: docs/lib/accessibility-audit.ts (one audit session per product; OpenAEV’s axe figures are computed from docs/lib/audits/) and docs/lib/deferred.ts (a deferral is a decision, not a coverage figure). Each carries its refs, its date and its own upkeep rule.