Skip to content

Changelog

What changed in each release, newest first. Breaking changes are marked Breaking.

v1.4.1

Released Compare with the previous release

Resizable

  • A saved layout under autoSaveId is now drawn from the group's first client render instead of applied a render later, so content that measures its panel in a mount effect (a canvas fitting its pages, for example) measures the restored split rather than the default one.
  • Added an onReady callback, fired once when the layout first settles — restored under autoSaveId or resolved from defaultSizes — for content that mounts hidden or whose panels aren't direct Resizable.Panel children and so can't measure at mount.

v1.4.0

Released Compare with the previous release

AppBar

  • Breaking: Removed the flat AppBarRoot, AppBarLeading, AppBarTitle and AppBarTrailing exports. Use the namespace properties instead — AppBar.Root, AppBar.Leading, AppBar.Title, AppBar.Trailing.

Button

  • Breaking: tone now defaults to neutral instead of primary, so a plain <Button> renders as a gray control rather than the accent color. A view typically has many buttons and one call to action; keep tone="primary" for the action you want found, and add it explicitly wherever a button relied on the old default.

Card

  • Breaking: Removed the flat CardRoot, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter and CardMedia exports — Card is now available only as its namespace object (Card.Root, Card.Header, …). A namespace object crosses a Server Component boundary as an opaque reference whose properties read as undefined at runtime, so a card built from server-fetched data now needs its own small Client Component wrapper.

Combobox

  • Breaking: Removed the flat ComboboxRoot, ComboboxLabel, ComboboxInputGroup, ComboboxInput, ComboboxTrigger, ComboboxValue, ComboboxIcon, ComboboxClear, ComboboxChips, ComboboxChip, ComboboxChipRemove, ComboboxPopup, ComboboxList, ComboboxEmpty, ComboboxStatus, ComboboxItem, ComboboxGroup, ComboboxGroupLabel, ComboboxSeparator, ComboboxRow and ComboboxCollection exports. Use the Combobox.* namespace properties instead; useComboboxFilter and useComboboxFilteredItems are unaffected.

DatePicker

  • Breaking: Removed the flat DatePickerRoot, DatePickerTrigger, DatePickerValue, DatePickerIcon, DatePickerPopup, DatePickerCalendar, DatePickerFooter and DatePickerClear exports. Use the DatePicker.* namespace properties instead.

Field

  • Breaking: Removed the flat FieldRoot, FieldLabel, FieldDescription, FieldError and FieldItem exports. Use the Field.* namespace properties instead.

Fieldset

  • Breaking: Removed the flat FieldsetRoot and FieldsetLegend exports. Use Fieldset.Root and Fieldset.Legend.

InputGroup

  • Breaking: Removed the flat InputGroupRoot, InputGroupInput, InputGroupTextarea, InputGroupAddon, InputGroupText and InputGroupButton exports. Use the InputGroup.* namespace properties instead.

NumberField

  • Breaking: Removed the flat NumberFieldRoot, NumberFieldGroup, NumberFieldInput, NumberFieldIncrement, NumberFieldDecrement, NumberFieldScrubArea and NumberFieldScrubAreaCursor exports. Use the NumberField.* namespace properties instead.

OTPField

  • Breaking: Removed the flat OTPFieldRoot, OTPFieldInput and OTPFieldSeparator exports. Use the OTPField.* namespace properties instead.

Resizable

  • Breaking: Removed the flat ResizableGroup, ResizablePanel and ResizableHandle exports. Use Resizable.Group, Resizable.Panel and Resizable.Handle.

Select

  • Breaking: Removed the flat SelectRoot, SelectLabel, SelectTrigger, SelectValue, SelectIcon, SelectPopup, SelectItem, SelectGroup, SelectGroupLabel and SelectSeparator exports. Use the Select.* namespace properties instead.

Table

  • Breaking: Removed the flat TableContainer, TableRoot, TableCaption, TableHeader, TableBody, TableFooter, TableRow, TableHead and TableCell exports — Table is now available only as its namespace object. The same Server Component caveat as Card applies: Table.Root and friends do not resolve across an RSC boundary, so a table of server-fetched rows now needs a Client Component wrapper.

Design tokens & motion

  • The focus ring now grows outward from just inside a control's edge while it fades in, and shrinks back on blur, instead of snapping into place. Three new tokens drive the pace: --forte-focus-ring-duration (--forte-duration-normal), --forte-focus-ring-ease (--forte-ease-standard) and --forte-focus-ring-travel (--forte-travel-sm, 0px under reduced motion, where the ring simply fades in place).
  • --forte-focus-ring-inner is now brand-colored — the accent ramp's text step (--forte-color-primary-text, held to 4.5:1 against the page) — instead of a fixed near-black/near-white pair, so the ring now recomputes per theme scope's seed instead of looking identical everywhere.

v1.3.0

Released Compare with the previous release

Resizable

  • Added expandOnClick to Panel, default true: a click or tap on the handle beside a collapsed panel now reopens it back to its previous size (not minSize), with the handle showing a one-way resize cursor pointing the way it will move to say so. Dragging the handle open still works wherever collapseOnDrag allows, snapping open at the same threshold point it snaps shut at, so both directions feel like one control. Enter now also reopens a shut panel whenever a click or a drag would, matching whichever gesture is enabled; set expandOnClick to false for a divider that reopens only by drag, or, with collapseOnDrag also off, only through the collapsed prop.
  • Fixed a shut panel with collapseOnDrag off also refusing to be dragged open — the prop now applies the same in both directions, so a divider that cannot be dragged shut behaves the same as one that cannot be dragged open.
  • Fixed a drag that reopens a collapsed panel past its snap point sometimes leaving a neighboring panel's size unaffected when room was actually available: the reopening panel can now borrow from the nearest shrinking panels (down to their own minimums) to fund the snap, rather than only from whatever slack the current drag step already freed.

v1.2.0

Released Compare with the previous release

Resizable

  • Added collapseOnDrag to Panel, default true. Set to false, the divider handle can no longer collapse or reopen the panel by dragging past its threshold or pressing Enter — the drag stops at minSize and a shut panel stays shut under a drag — while the collapsed prop and a consumer's own toggle still work, for a sidebar whose only route to closed is deliberate.
  • A panel given a px size now holds that length across a window resize instead of drifting back toward a percentage: it is anchored at that pixel width (or height) while the group's percentage-sized panels share what is left, and it comes back at the same length when restored from autoSaveId storage.
  • Fixed the divider staying lit after a pointer drag: a drag focuses the handle, and the browser may treat that as keyboard focus, so the thickened line and grip border now light up only for genuine :focus-visible (keyboard) focus, matching the outline suppression already in place. A drag that never receives its release — capture refused or lost — now ends cleanly on lostpointercapture, pointerup, pointercancel or blur instead of leaving the drag overlay mounted until reload.
  • Fixed a collapsible panel snapping shut in a single frame when a drag crossed its collapse threshold; the jump now eases in on a spring curve (--forte-ease-spring-precise / --forte-duration-spring-precise) and a drag that keeps moving during the ease retargets smoothly instead of fighting it.
  • Fixed a group restored from autoSaveId visibly sliding in from its default sizes before snapping to the saved layout: sizes now apply before the group's first paint (via a small inline script on the server-rendered markup, falling back to a post-mount restore under a strict CSP or a custom storage).
  • Thinned the divider's active (hover/focus/dragging) line from 3px to 2px.

Design tokens & motion

  • --forte-color-border, --forte-color-border-muted and --forte-color-border-strong are now translucent (color-mix against transparent) instead of opaque gray steps, so every 1px edge reads as a hairline instead of carrying full ramp contrast (previously up to 2.1:1 in dark mode, now 1.2–1.7:1). A consumer relying on the previous opaque values — for compositing against a custom background, or reusing the token outside its usual surface — will see the new, lighter edges. The prefers-contrast: less override now derives from the same mix rather than an opaque gray-6, so it stays lighter than the default rather than overriding it.

Pagination

  • Fixed a doubled-looking seam between adjacent slots in the joined variant: two overlapping translucent borders summed to a darker line than the strip's outer edge, so a slot now paints only one side of each shared edge.

v1.1.1

Released Compare with the previous release

  • Added press feedback to NavList.Link rows: the same hover lift and press squash as Button, via the new shared .forte-pressable pattern, so rows and buttons feel like one control set.

Design tokens & motion

  • Extracted Button's press geometry (hover lift, press squash, spring release) into a shared .forte-pressable class in patterns.css that any interactive part can compose for the same feel. It reads generic --forte-press-lift / -hover-scale / -scale / -duration / -ease slots, falling back to Button's own defaults when a component maps nothing onto them.

v1.1.0

Released Compare with the previous release

Shimmer

  • Added Shimmer, a band of light sweeping through a run of text for status messages that are themselves the content (e.g. "Generating response…"), as an alternative to pairing a Spinner with a label. The text stays real, selectable text — only the paint animates. Props: active (default true) toggles the sweep without swapping components, once sweeps a single pass instead of looping, and reverse sweeps against the reading direction (the default follows dir). Styled via data-* attributes and --forte-shimmer-* custom properties; under reduced motion the band does not travel or show, leaving plain colored text.

v1.0.1

Released Compare with the previous release

create-forte-ui

  • Fixed the Next.js + Tailwind starter layout to import globals.css before @forte-ui/react, preserving the intended cascade-layer order (theme, base, forte, components, utilities) so Preflight no longer wins over the library's components.

v1.0.0

Released Compare with the previous release

General

  • Added an MIT LICENSE file to each publishable package (@forte-ui/react, forte-ui, create-forte-ui).

v1.0.0-beta.2

Released Compare with the previous release

General

  • Added homepage and repository fields to @forte-ui/react's package.json.

v1.0.0-beta.0

Released Compare with the previous release

AppBar

  • Added a scrollThreshold prop to AppBar.Root: how far, in pixels, the scroll container has to move before the bar counts as scrolled. 0 (the previous, and default, behaviour) is the first pixel past the bar's resting position; a larger value holds data-scrolled — and everything keyed on it, including elevateOnScroll and a consumer's own [data-scrolled] rule — off until the page has moved that far under it. hideOnScroll is unaffected, since data-hidden follows scroll direction rather than distance.
  • Slowed the bar's surface transition (fill, edge, shadow) from --forte-duration-fast to --forte-duration-normal via the --forte-app-bar-duration knob's default.

Drawer

  • Added a scrollArea prop to Drawer.Content (default true): the body now scrolls inside a composed ScrollArea rather than a plain overflow: auto box, so the scroll track and the edge-fade sit flush against the drawer's own edge instead of inset over the text, and the scrollport is a tab stop only while there is something to scroll. Set it to false for a body that brings its own scrolling — a virtualised list, a map, an embedded editor. Ships with the --forte-scroll-area-fade-size knob, set by default to the drawer's own padding.
  • Fixed the popup overflowing a narrow phone screen: its width now resolves against an explicit grid track sized to the available space instead of an implicit auto track sized to the popup's own width, which had let max-inline-size: 100% resolve circularly and leave the far edge of a md drawer hanging off a 375px screen.
  • Fixed a nested drawer's dimming overlay drawing a second, phantom scrollbar (most visible on Android): the overlay used to reach past the popup's edge with a negative inset, which counted as scrollable overflow on the popup's own fallback scroll container; it now reaches the same distance with a spread box-shadow, which paints outside the box without adding to anything's scrollable area.

Select

  • Breaking: Select.Popup now defaults align to Base UI's own default, "center", instead of "start". Every Select.Popup that did not set align explicitly now opens centred on its trigger rather than aligned to its start edge; pass align="start" to restore the previous position.

Tabs

  • Added an autoHeight prop to Tabs.Root (default false): when on, the panel area is measured and the root's height transitions between panels instead of snapping to the new panel's size, and keeps following the active panel afterwards as its content changes — an image loading, a disclosure opening. Ships with a new --forte-tabs-auto-height-duration knob (defaults to --forte-duration-move, the same clock the Tabs indicator runs on) controlling the transition length. While it is on, the panel is start-aligned rather than stretched to the track.

Design tokens & motion

  • Suppressed the platform's translucent tap-highlight box on every part the library renders, via one rule on [data-forte] in patterns.css rather than a scattered per-component declaration. It ignored border-radius, covered the whole element rather than the pressed part, and lingered after release; every interactive part already draws its own press state, so this is safe everywhere the library controls.
  • Added an opt-in forte-reset class (switched on by importing @forte-ui/react/styles/reset.css) that also suppresses the tap highlight for the rest of an app, for apps that draw their own press states outside the library's parts.
  • Breaking: Moved the reset stylesheet's box-sizing rule into its own forte.reset sublayer instead of the bare forte layer, fixing it silently outranking every other forte.* sublayer, including forte.components. An app whose own styles were being outranked by the old bare-forte placement may now see those styles win where they previously lost, since forte.reset sits below the other forte.* sublayers.
  • Fixed a .forte-visually-hidden span adding phantom scrollable overflow to a distant scrolling ancestor — seen with a ColorPicker nested low inside a Drawer, which grew a second, invisible-until-dragged scrollbar on the drawer's popup — by pinning the span to its containing block's start corner instead of leaving it to lay out against the nearest positioned ancestor.

create-forte-ui

  • Scaffolded Vite and Next.js apps now import @forte-ui/react/styles/reset.css and add the forte-reset class to <html>, switching on the library's blanket reset — box-sizing plus the tap-highlight suppression — as the new project's baseline.

General

  • @forte-ui/react/docs-data/components.json — the generated component catalogue as data — is now an exported subpath.

Full history

This page carries the 10 most recent releases. The 6 releases before them — back to v1.0.0-alpha.1 on August 30, 2026 — are in CHANGELOG.md on GitHub, along with everything above.