# Radix UI → Base UI props mapping: progress, scroll-area, separator, avatar, toast, form Sources: radix-ui/website `data/primitives/docs/components/*.mdx` (full inline prop tables) and base-ui.com `/react/components/{progress,scroll-area,separator,avatar,toast,form,field,fieldset}.md` (fetched 2026-07-02, `@base-ui/react`, formerly `@base-ui-components/react`). Universal conventions (apply to every part below, not repeated per table): - `asChild` (boolean) → `render` (`ReactElement | ((props: HTMLProps, state) => ReactElement)`). Signature changed: `` → `} />`. - Base UI `className` and `style` also accept a function of the part's `State` object. - Every Base part exposes `Part.Props` and `Part.State` types (e.g. `Progress.Root.Props`). --- # progress Part mapping: `Progress.Root` → `Progress.Root`, `Progress.Indicator` → `Progress.Indicator` (now MUST be nested in the new `Progress.Track`). Base UI adds `Track`, `Label`, `Value` parts. The primitive computes the Indicator fill width itself (inline style), so the Radix pattern `style={{ transform: translateX(-(100 - value)%) }}` on Indicator is deleted, not ported. ## Progress.Root → Progress.Root | Radix prop | Type / default | Base UI equivalent | Migration note | | --- | --- | --- | --- | | `asChild` | `boolean` / `false` | `render` | Signature changed (see header). | | `value` | `number \| null` / - | `value` | Same. Required in Base UI (default `null`). `null` = indeterminate in both. | | `max` | `number` / - | `max` | Same. Base UI default `100`; Base UI also adds `min` (default `0`). | | `getValueLabel` | `(value: number, max: number) => string` / - | `getAriaValueText` | Renamed + signature changed: Base UI is `(formattedValue: string \| null, value: number \| null) => string`. Percent math is gone; use `format`/`locale` for formatting instead. | ## Progress.Indicator → Progress.Indicator | Radix prop | Type / default | Base UI equivalent | Migration note | | --- | --- | --- | --- | | `asChild` | `boolean` / `false` | `render` | Only prop. Nest inside `Progress.Track`; width is set by the primitive. | ### Base UI only props worth knowing - Root: `min` (`0`), `format` (`Intl.NumberFormatOptions`), `locale` (`Intl.LocalesArgument`), `aria-valuetext`. - New parts: `Progress.Track` (contains Indicator), `Progress.Label` (accessible label, ``), `Progress.Value` (formatted value text, ``, `children` render fn `(formattedValue, value) => ReactNode`). ### Data attributes | Radix | Base UI | | --- | --- | | `[data-state="loading"]` | `[data-progressing]` (boolean-presence attrs replace the enum) | | `[data-state="complete"]` | `[data-complete]` | | `[data-state="indeterminate"]` | `[data-indeterminate]` | | `[data-value]`, `[data-max]` | Dropped. Read `value` in a `className`/`style` state function or set your own attribute. | All Base attrs are present on Root, Track, Indicator, Label, and Value alike. State type: `{ status: 'indeterminate' | 'progressing' | 'complete' }`. ### CSS variables None on either side. --- # scroll-area Part mapping: `ScrollArea.Root` → `ScrollArea.Root`, `ScrollArea.Viewport` → `ScrollArea.Viewport`, `ScrollAreaScrollbar` → `ScrollArea.Scrollbar`, `ScrollAreaThumb` → `ScrollArea.Thumb`, `ScrollArea.Corner` → `ScrollArea.Corner`. Base UI adds `ScrollArea.Content` (wraps content inside Viewport, needed for horizontal overflow measurement). ## ScrollArea.Root → ScrollArea.Root | Radix prop | Type / default | Base UI equivalent | Migration note | | --- | --- | --- | --- | | `asChild` | `boolean` / `false` | `render` | Signature changed. | | `type` | `"auto" \| "always" \| "scroll" \| "hover"` / `"hover"` | Dropped | Visibility is CSS-driven: style Scrollbar `opacity` against `[data-hovering]`/`[data-scrolling]` (hover/scroll behavior), or always-visible CSS for `"always"` (+ `keepMounted` on Scrollbar). `"auto"` is the default mount behavior (scrollbar only mounts when scrollable). | | `scrollHideDelay` | `number` / `600` | Dropped | Reproduce with a CSS `transition-delay` on the scrollbar's opacity transition. | | `dir` | `"ltr" \| "rtl"` / - | Dropped | Base UI reads direction from the DOM (`dir` attribute) / its DirectionProvider utility; no per-component prop. | | `nonce` | `string` / - | Dropped | No documented CSP nonce equivalent. | ## ScrollArea.Viewport → ScrollArea.Viewport | Radix prop | Type / default | Base UI equivalent | Migration note | | --- | --- | --- | --- | | `asChild` | `boolean` / `false` | `render` | Same part role (the scrollable container). Wrap children in `ScrollArea.Content` when horizontal scrolling matters. | ## ScrollAreaScrollbar → ScrollArea.Scrollbar | Radix prop | Type / default | Base UI equivalent | Migration note | | --- | --- | --- | --- | | `asChild` | `boolean` / `false` | `render` | Signature changed. | | `forceMount` | `boolean` / - | `keepMounted` | Renamed; `boolean`, default `false`. Keeps the element in the DOM when the viewport is not scrollable. | | `orientation` | `"horizontal" \| "vertical"` / `"vertical"` | `orientation` | Same, same default. | ## ScrollAreaThumb → ScrollArea.Thumb | Radix prop | Type / default | Base UI equivalent | Migration note | | --- | --- | --- | --- | | `asChild` | `boolean` / `false` | `render` | Only prop on both sides. | ## ScrollArea.Corner → ScrollArea.Corner | Radix prop | Type / default | Base UI equivalent | Migration note | | --- | --- | --- | --- | | `asChild` | `boolean` / `false` | `render` | Only prop on both sides. | ### Base UI only props worth knowing - Root: `overflowEdgeThreshold` (`number | Partial<{ xStart; xEnd; yStart; yEnd }>`, default `0`), threshold before the overflow edge attributes flip. - New part: `ScrollArea.Content` (div inside Viewport; same overflow data attributes as Root). ### Data attributes | Radix | Base UI | | --- | --- | | Scrollbar `[data-state="visible" \| "hidden"]` | Dropped. Use `[data-hovering]`, `[data-scrolling]`, and `[data-has-overflow-x/y]` on Scrollbar to drive visibility styles. | | Scrollbar/Thumb `[data-orientation]` | Same (`data-orientation` on Scrollbar and Thumb). | | - | New, on Root/Content/Viewport/Scrollbar: `data-has-overflow-x`, `data-has-overflow-y`, `data-overflow-x-start/end`, `data-overflow-y-start/end`, `data-scrolling`; Scrollbar also `data-hovering`. | ### CSS variables Radix's scroll-area docs list no CSS variables (its implementation ships undocumented `--radix-scroll-area-thumb-*`/`corner-*` vars). Base UI documents: | Base UI variable | Where | | --- | --- | | `--scroll-area-corner-width`, `--scroll-area-corner-height` | Root | | `--scroll-area-thumb-width`, `--scroll-area-thumb-height` | Scrollbar | | `--scroll-area-overflow-x-start/end`, `--scroll-area-overflow-y-start/end` | Viewport (pixel distance from each edge, great for scroll fades) | --- # separator Part mapping: `Separator.Root` → `Separator` (callable single part, no `.Root`). ## Separator.Root → Separator | Radix prop | Type / default | Base UI equivalent | Migration note | | --- | --- | --- | --- | | `asChild` | `boolean` / `false` | `render` | Signature changed. | | `orientation` | `"horizontal" \| "vertical"` / `"horizontal"` | `orientation` | Same, same default (`Orientation` type). | | `decorative` | `boolean` / - | Dropped | Base UI's separator is always semantic (`role="separator"`). For a purely visual rule, render a plain `