Releases: ngrok/mantle
@ngrok/mantle@0.76.5
Patch Changes
-
#1263
3703172Thanks @cody-dot-js! - Add expandable-row support toDataTablefor inline, per-row detail panels — restoring the click-to-expand record inspection pattern that the migration offGenericTablelost.New API, all driven by native TanStack Table expansion state (no invented state):
DataTable.Rowgains an optionalrenderExpandedprop — the primary, ergonomic path. When the row is expanded it renders its data row plus a sibling detail row holding the returned content, so consumers no longer hand-write theFragment, thegetIsExpanded()conditional, or the extra<tr>. It is called lazily (only while open), so collapsed rows never build their panel.DataTable.Rowalso now setsdata-expandedas a styling hook.DataTable.RowExpandButton— an accessible+/−toggle (@phosphor-icons/reactPlus/Minus) for a leadingcolumnHelper.displaycolumn. Renders a real<button>that setsaria-expandedand (only while expanded)aria-controls, stops click propagation so it never fires a row-levelonClick, lets a consumeronClickveto the toggle viaevent.preventDefault(), and renders nothing whenrow.getCanExpand()isfalse.DataTable.ExpandHeader— a narrow<th>for the toggle column, mirroringDataTable.ActionHeader.DataTable.ExpandedRow— the sibling<tr>renderExpandedwraps content in, also exported for full control (customcolSpan, multiple panels, bespoke markup). Spans every visible column, carries theidthatRowExpandButtontargets viaaria-controls, suppresses its top divider so it reads as one block with its parent row, sits on an opaque surface so it coexists with a sticky action column, and exposesdata-expanded-contentfor styling.expandedRowId(row)— the exported helper that derives the shared, stable DOM id used by the toggle'saria-controlsand the expanded row'sid.
Add
jsonCodeBlockValueandjsonToShikiHtmlto@ngrok/mantle/code-block: an ultralight (~1 KB) client-side JSON syntax highlighter whose output is byte-for-byte identical to Mantle's server/build-time Shiki highlighting — without shipping Shiki, any grammar, or WASM to the browser. Because Mantle highlights with a CSS-variables theme, only tokenization needs to happen client-side; the colors already live in CSS. Ideal for rendering a row's underlying object as highlighted JSON inside aDataTable.ExpandedRowwith no build-time plugin and no server roundtrip. Multi-line objects and arrays are collapsible by default (foldable, on), reusing the samecomputeJsonFoldRanges+ fold runtime as every other JSONCodeBlock, so the fold markup and behavior are identical.
@ngrok/mantle-vite-plugins@1.0.15
Patch Changes
-
#1262
9fb7022Thanks @dependabot! - Bumpoxc-parserto0.137.0. -
Updated dependencies [
9fb7022]:- @ngrok/mantle-server-syntax-highlighter@1.1.5
@ngrok/mantle-server-syntax-highlighter@1.1.5
Patch Changes
- #1262
9fb7022Thanks @dependabot! - Bumpoxc-parserto0.137.0.
@ngrok/mantle@0.76.4
Patch Changes
-
#1257
7a32ee9Thanks @cody-dot-js! - Simplify several costly CSS selectors to cheaper, equivalent forms. All changes are behavior-, theming-, and a11y-preserving — no public API changes.- CodeBlock fold gutter (
mantle.css+decorate-highlighted-html.ts): the gutter-reservation rule no longer probes every line with a per-line relational:not(:has(> .mantle-code-fold-toggle))(whose style-recalc cost scaled with line count). A single per-<pre>:has()now scopes the rule, content gets the gutter margin by default, and the sparse opener lines are taggedmantle-code-line-openerso CSS can reset theirs. Measured in Chromium on a fold-enabled block, this removes ~0.5 ms of style-recalc at 5,000 lines and ~3.6 ms at 20,000 lines, while keeping HTML payload flat (only opener lines gain a class). - Command group heading (
command.tsx): the five**:[[cmdk-group-heading]]:*deep-descendant scans are now direct-child[&>[cmdk-group-heading]]:*selectors (cmdk renders the heading as a direct child of the group). Identical specificity, smaller match scope. - Command item icons (
command.tsx): the brittle[&_svg:not([class*='size-'])]/[&_svg:not([class*='text-'])]substring-attribute scans are replaced with:where()-wrapped defaults ([:where(&_svg)]:size-5/[:where(&_svg)]:text-muted), matching theLabelprecedent. Consumer icon size/color classes still override the defaults cleanly, without the substring scan or its false matches (e.g.text-sm). - HorizontalSeparatorGroup (
separator.tsx): the universal-descendant[&_*:not([data-separator])]:shrink-0is now a direct-child[&>*:not([data-separator])]:shrink-0.flex-shrinkonly affects direct flex items, so this collapses an unbounded subtree walk to a single parent check with no rendered difference.
- CodeBlock fold gutter (
-
#1256
1a48962Thanks @cody-dot-js! -ButtonandIconButtonnow defaulttypeto"button"instead of requiring it.The
typeprop is relaxed from required to optional on both components; when omitted it renderstype="button", matching the wider React ecosystem (Radix, shadcn, MUI, …) and neutralizing the native<button>accidental-form-submit footgun. This is backward compatible — every existing call site already passestype, so nothing changes for them; omittingtypesimply stops being a compile error.Forms note: because the default is now
"button", aButton/IconButtonthat relies on native form submission must opt in withtype="submit".When
asChildis used,typecontinues to have no effect and is not forwarded to the child. -
#1254
b5b72bcThanks @cody-dot-js! - Stop publishing source maps. The.js.mapfiles were ~58% of the package's unpacked size (and compressed tarball) and embedded the full original source viasourcesContent, despitesrc/not being shipped. Dropping them more than halves the published package.This affects nothing consumers import at runtime. The typed
.d.tssurface (with its JSDoc and@exampleblocks) and the bundled agent-discovery artifacts (dist/agent.json,dist/llms.txt) are unchanged; only stepping into mantle's original source in a debugger is no longer possible.
@ngrok/mantle@0.76.3
Patch Changes
-
#1241
f7be346Thanks @cody-dot-js! - Updatereact-day-pickerto10.0.1(from9.14.0) and bump thetailwindcsspeer dependency to^4.3.1. TheCalendarcomponent already used the v9+ API surface — no removed navigation/focus/event props, formatter or label aliases, or renamedclassNameskeys — so this is a transparent dependency bump with no public API changes. -
#1247
846f5bdThanks @cody-dot-js! - Fix two issues withCheckbox's indeterminate handling:- A controlled checkbox toggling through
"indeterminate"(e.g. a table "select all" header cycling unchecked → indeterminate → checked) logged React's "changing a controlled input to be uncontrolled" warning. The indeterminate frame now keepscheckeda boolean, so the input stays controlled for its entire lifetime. - A controlled
checked="indeterminate"set on mount did not render the indeterminate visual — two competing effects clobbered each other. The nativeindeterminateDOM property is now driven by a single effect keyed on the effective checked state, so it renders correctly on first paint and on every update.
Add
selectAllCheckedto@ngrok/mantle/checkbox— a helper that resolves the tri-statecheckedvalue (true/"indeterminate"/false) for a "select all" checkbox from{ allSelected, someSelected }selection counts, ready to pass straight toCheckbox. Encapsulates the correctness-prone tri-state branch every multi-select list reinvents. Also exports theCheckedStatetype. - A controlled checkbox toggling through
-
#1247
846f5bdThanks @cody-dot-js! - Update theDataTablesource JSDoc@exampleblocks so the regenerated.d.ts,llms.txt, and agent component manifest teach canonical patterns instead of throwaway ones: the two empty states (anEmptyhosted inDataTable.EmptyRow— "no data yet" vs. "no results for the active filter", with aClear filtersreset) and pagination viaCursorPaginationwith a page-size dropdown (replacing hand-rolled prev/nextButtons). No runtime API changes. -
#1249
44ee551Thanks @cody-dot-js! - Drive thescroll-fade-xedge-fade utility with a CSS scroll-driven animation instead of JS-toggleddata-scroll-left/data-scroll-rightattributes, and add a matchingscroll-fade-yutility for vertical scroll containers. Single-edge variants —scroll-fade-t,scroll-fade-b,scroll-fade-l,scroll-fade-r— are also available for containers that should fade only one edge (e.g. a sidebar that fades content scrolling under a sticky header but stays flush at the bottom).TableandTabsnow render their horizontal edge fades purely in CSS: theTabs.Listeffect no longer runs a scroll listener,ResizeObserver, orMutationObserverfor the fade (it only keeps a keyboard-focused trigger scrolled into view), andTableno longer writes the fade attributes. Consumers can still pin an edge opaque by overriding--_fade-left/--_fade-right(the animation drives the upstream--_scroll-fade-*vars). Whereanimation-timeline: scroll()is unsupported (Firefox stable as of mid-2026) the fade is simply absent — content is never clipped. -
#1248
3a234e0Thanks @cody-dot-js! - Update Radix UI dependencies to their latest patch/minor releases:@radix-ui/react-accordionto1.2.14,@radix-ui/react-dialogto1.1.17,@radix-ui/react-dropdown-menuto2.1.18,@radix-ui/react-hover-cardto1.1.17,@radix-ui/react-popoverto1.1.17,@radix-ui/react-progressto1.1.10,@radix-ui/react-selectto2.3.1,@radix-ui/react-sliderto1.4.1,@radix-ui/react-slotto1.3.0,@radix-ui/react-switchto1.3.1,@radix-ui/react-tabsto1.1.15, and@radix-ui/react-tooltipto1.2.10. No public API changes. -
#1239
9b00072Thanks @cody-dot-js! - Surface each component's JSDoc@exampleblocks in the agent-facing component manifest (/api/components.json), giving agents copy-pasteable canonical usage without a network lookup. Fix two malformed examples caught in the process:Sheetexamples usedopOpenChangeinstead ofonOpenChange, andSandboxedOnClick's example was missing its closing code fence. Also documents theFieldslot-order anti-pattern — help text (Field.Description) renders belowField.Control, not above it.
@ngrok/mantle-vite-plugins@1.0.14
Patch Changes
-
#1241
f7be346Thanks @cody-dot-js! - Update theoxc-parserdependency to0.136.0(from0.135.0). -
Updated dependencies [
f7be346]:- @ngrok/mantle-server-syntax-highlighter@1.1.4
@ngrok/mantle-server-syntax-highlighter@1.1.4
Patch Changes
- #1241
f7be346Thanks @cody-dot-js! - Update theoxc-parserdependency to0.136.0(from0.135.0).
@ngrok/mantle@0.76.2
Patch Changes
- #1233
fa978b0Thanks @cody-dot-js! - RefineEmptyandWellstyling:Emptyuses tighter padding (p-6),Empty.Iconis smaller with a neutral color,Empty.TitleandEmpty.Descriptionadopt smaller sans-serif text with a muted description, andWelluses the muted card border.
@ngrok/mantle@0.76.1
Patch Changes
- #1229
a569ca3Thanks @cody-dot-js! - Remove the unused@uidotdev/usehooksdependency. It was never imported by any mantle code; consumers no longer install it transitively.
@ngrok/mantle@0.76.0
Minor Changes
-
#1227
fbec001Thanks @cody-dot-js! - fix(mantle): Dialog.Footer renders children in DOM orderDialog.Footerpreviously appliedflex-row-reverse, laying its children out
right-to-left so the DOM order was the visual mirror of the source. It now uses
flex justify-endand renders children in DOM order, matchingSheet.Footer
andAlertDialog.Footer. This also makes keyboard tab order follow visual
order.Breaking visually: footers with two or more children that relied on the
reversal will now render in the opposite order. Reverse the direct children of
each affectedDialog.Footer(conventionally secondary/cancel first, primary
last) to preserve the previous appearance. See the migration guide at
https://mantle.ngrok.com/migrations/dialog-footer-dom-order-migration.