Repository navigation
UIKit v8 introduces composable providers, a new list foundation, responsive layout APIs, and updated themes. This major release also removes deprecated APIs and moves older components to the legacy entry point.
Highlights
- Composable providers:
Providercombines theme, language, layout, component defaults, and mobile settings. Feature providers let you configure each independently. - New List and stable Menu: selection, virtualization, and drag-and-drop are separate list layers.
Menusupports composable items and submenus. - Responsive layouts: new
Gridand responsive style props forBox,Flex,Container,Row, andCol. - Stable APIs:
ColorPicker,FileDropZone, anduseDropZonemove to the root entry point. - More flexible Select: non-string option values, custom selection indicators, mobile sheet titles, and rendering the whole selection with
renderSelectedOptions. - Contrast palettes:
Buttongainscontrast,contrast-inverted,contrast-light, andcontrast-darkviews, backed by Themer v2 semantic tokens.
⚠️ Breaking changes
React and dependencies
React and React DOM 18 or 19 are required; support for 16 and 17 is removed.
Virtualization and drag-and-drop packages become optional peers: /virtualizer needs @tanstack/react-virtual, /hello-pangea-dnd needs @hello-pangea/dnd, and /legacy needs @hello-pangea/dnd, react-window, and react-virtualized-auto-sizer. The root entry point needs none of these. lodash is replaced with es-toolkit; declare it yourself if your application imports it.
Providers
Replace the application-level ThemeProvider with Provider. ThemeProvider now handles only theme and direction; language, layout, and defaults belong to their feature providers. Nested providers are scoped.
Component entry points
The old List, Menu, DropdownMenu, Table, its HOCs, and TableColumnSetup move to /legacy. Root List and Menu have new APIs; ActionsPanel replaces dropdown with menu and uses the new menu item API.
Legacy Breadcrumbs, Popover, and Tabs are removed. The experimental useList, TreeList, and TreeSelect family moves out of UIKit to @gravity-ui/normalized-list. /unstable is now empty; promoted APIs use stable names without the prefix. Update affected imports, CSS selectors, and component-default keys.
Select
Select uses the new List. Replace virtualizationThreshold with a ListVirtualizer wrapper; without it, all options render. renderSelectedOption becomes renderSelectedOptions; option types become SelectOptionProps and SelectOptionGroupProps, while SelectItem components become SelectOption components.
Replace option text with getOptionText; read filter handlers from renderFilter's inputProps. Option keys must be unique across groups. The popup anchors to the control, and its default offset becomes 4px. Rendering, DOM roles, and CSS selectors change; mobile close callbacks fire when closing starts, and controlled filters are preserved.
Layout and sizes
Replace the old spacing objects and layout shortcuts with responsive style props. Numeric gaps and gutters now mean pixels; use spacing-* tokens for scale values. Row uses CSS Grid; unsized columns span a full row, and sized columns require a parent Row. Layout components no longer enforce border-box.
Size names xxs, xxl, and xxxl become 2xs, 2xl, and 3xl, including breakpoint keys and CSS modifiers.
Layout migration · Size renames
Themes and Button views
Regenerate custom themes with Themer v2. The SCSS theme module and g-theme-* mixins are removed; --g-color-base-light* tokens have new contrast replacements. Accent font weights use per-group tokens. Replace normal-contrast with contrast-light; recreate outlined-contrast and flat-contrast through the Button CSS API.
Theme migration · Button migration
Overlays and mobile behavior
Modal, Dialog, and Popup remove deprecated dismissal callbacks in favor of onOpenChange and OpenChangeReason. Popup uses anchorElement; Dialog replaces size with maxWidth and fullWidth. Sheet replaces visible/onClose with open, defaultOpen, and onOpenChange.
Mobile modals are enabled whenever mobile is enabled; __experimentalMobileModals is removed. Automatic height animations are removed. Dialog spacing changes, and desktop footer buttons no longer stretch.
Overlay migration · Sheet migration
Other API and visual changes
Removed APIs include Button/Link extraProps, input error and onKeyPress, Avatar.alt, useColorGenerator.theme, and layerschange's layersCount. HelpMark.iconSize becomes size; physical icon/arrow positions become start/end.
Lang and Platform become const objects with union types. Saved getConfig() results no longer track subsequent updates. Custom language keysets need the new drag-and-drop and file-drop keys.
List, Select, and Menu row heights align with controls. Checkbox, Radio, and Switch typography and spacing change; Progress loses automatic centering. Hover styles require hover-capable devices, and button-reset preserves native focus outlines. Review custom CSS and screenshot baselines.
API replacements · Visual and type changes
Full changelog
Changes by component, layout primitive, hook, and package API
Components and providers
Provider, ThemeProvider, LangProvider, LayoutProvider, and MobileProvider
- Add application-level
Provider, composing theme, language, layout, component defaults, mobile settings, and the shared tooltip delay group. - Restrict
ThemeProviderandThemeProviderPropsto theme and direction. Movelang/fallbackLangtoLangProvider,layouttoLayoutProvider, anddefaultPropstoDefaultPropsProvider;Provideraccepts them together. - Export
LangProviderandLayoutProviderfor independent feature configuration. Nested layout providers inherit parent settings and merge local configuration. - Make nested providers and theme scopes always scoped, including when
scoped={false}. Theme scopes preserve parent language, layout, defaults, and mobile settings; portals preserve local theme and direction. - Let
Provideraccept mobile settings directly. NestedProviderinstances use independent mobile and router defaults, so pass those settings explicitly when needed. - Remove
__experimentalMobileModalsfrom providers and the mobile context. Enable mobileModalandDialogrendering whenevermobileis enabled.
ActionsPanel
- Use the stable
Menufor overflow actions and submenus. - Rename
ActionsPanelItem.dropdowntomenu; itsitemnow acceptsMenuItemProps. Replacetextwithchildren,actionwithonClick,iconStartwithicon, andiconEndwitharrow. - Replace nested
itemsarrays with childMenucomponents. Pass native props directly instead of throughextraProps, and omit hidden actions when building the array. - Update overflow markup and CSS selectors to
g-menu-item. The overflow menu no longer closes automatically when an ancestor scrolls.
Avatar
- Remove
alt. The image is decorative and renders withalt="".
Breadcrumbs
- Remove the legacy component and its related exports from
/legacy; use the current root component. - Rename the current component's translation keyset from
lab/BreadcrumbstoBreadcrumbs. ExistingBreadcrumbs.label_moreoverrides continue to work.
Button
- Remove
extraProps; pass native button, link, or custom-component props directly. This also applies to APIs based onButtonProps, including alert actions, menu triggers, ActionsPanel buttons, and Dialog footer buttons. - Remove
Button.Iconphysicalsidevaluesleftandright; usestartandendfor direction-aware positioning. - Add
contrast,contrast-inverted,contrast-light, andcontrast-darkviews. Removenormal-contrast,outlined-contrast, andflat-contrast; replacenormal-contrastwithcontrast-light, and use the CSS API for custom outlined or flat contrast buttons.
Checkbox, Radio, and RadioGroup
- Use
body-1typography for sizel; increase the Checkbox and Radio indicator to 18px at that size. - Use an 18px label line height for sizes
sandm, and align indicators with the first label line. - Update RadioGroup option spacing: horizontal gaps are 16px for
m/land 20px forxl; verticalxlgaps become 16px. - Draw the radio dot on
.g-radio__discinstead of its::beforepseudo-element. Use a 1px focus-outline offset.
ClipboardButton
- Add
tooltipPropsfor supported ActionTooltip settings, including placement, offset, portal behavior, disabled state, DOM props, QA props, andonOpenChange. - Participate in the shared tooltip delay group under
Provider.
ColorPicker
- Promote
unstable_ColorPickerand its props type toColorPickerandColorPickerPropsin the root entry point. Remove their/unstableexports.
Dialog
- Remove
onClose,onEscapeKeyDown,onOutsideClick, andonEnterKeyDown. Handle dismissal throughonOpenChange; useinitialFocus="apply"or form submission for Enter actions. - Remove
size; usemaxWidthandfullWidthfor the previous fixed-width behavior. - Remove automatic content-height animations and
disableHeightTransition. - Update header, body, footer, and close-button spacing. Remove the
g-dialog_has-closeclass. - Stop stretching desktop footer buttons and remove their 128px minimum width. Configure
propsButtonApply/propsButtonCancelto restore custom sizing; mobile buttons still stretch. - Use mobile rendering by default in mobile context.
Disclosure
- Remove physical
arrowPositionvaluesleftandright; usestartandend.
FileDropZone
- Promote
unstable_FileDropZonetoFileDropZonein the root entry point, together with its related types. Remove the old/unstableexports. - Include the
FileDropZonekeyset in the publicKeysetstype.
HelpMark and DefinitionList
- Rename
HelpMark.iconSizetosize, including component defaults and DefinitionList note objects. Supported values and the default remain unchanged.
Label
- Rename
size="xxs"tosize="2xs"and.g-label_size_xxsto.g-label_size_2xs.
Link
- Remove
extraProps; pass native anchor props directly. - Moving
target="_blank"to the root addsrel="noopener noreferrer"whenrelis not supplied. Review native props that previously could be overridden insideextraProps.
List
- Replace the root component with the former experimental List, using item getters, composable row rendering, keyboard navigation, and optional selection, virtualization, and drag-and-drop layers.
- Move the v7 List and its related types to
/legacy, with CSS blockg-list-legacy. The new List has no built-in filter; provide an input and filtering logic separately. - Promote
unstable_List,unstable_moveItem,unstable_useListFocusOwner, and the new List's related types to stable root names without the prefix. - Remove
lab-from the new List's CSS blocks. Replace old row selectors and QA conventions with the new row views, data attributes, and item IDs. - Keep the active row in view, ignore hover without pointer movement, and preserve focus across virtualization. Nested lists do not inherit the outer list's virtualization layer.
- Update section headers to accent typography with dividers between sections. Fix SCSS height-variable references for row and header sizing.
ListItemView
- Align minimum row heights with control sizes: 24, 28, 36, and 44px for
s,m,l, andxl. List, Select, and Menu rows follow this geometry. - Derive padding and header heights from the row height. Use
--g-list-item-view-min-heightand the row CSS API for custom geometry. - Support custom selection indication through the row view, with size-aware styling.
Menu and DropdownMenu
- Promote the former experimental Menu family to stable root exports, including
MenuItem,MenuTrigger, andMenuDivider. - Use
MenuItemchildren and atrigger, orinline, instead of the old Menu/DropdownMenu item APIs. - Move the previous Menu, DropdownMenu, and related types to
/legacy; mark legacy components deprecated. - Rename stable CSS blocks from
g-lab-menu*tog-menu*; legacy blocks becomeg-menu-legacyandg-dropdown-menu-legacy. Update Tabs overflow-menu selectors too. - Use
MenuLegacyfor legacy Menu defaults inDefaultPropsProvider; theDropdownMenukey remains unchanged.
Modal
- Remove
onClose,onEscapeKeyDown,onOutsideClick, andonEnterKeyDown; useonOpenChangefor dismissal and native keyboard or form handling for Enter actions. - Replace
ModalCloseReasonwith the publicOpenChangeReasontype. Escape and outside dismissal reasons becomeescape-keyandoutside-press. - Remove automatic content-height animations and
disableHeightTransition. - Use mobile rendering by default in mobile context.
NumberInput
- Remove the deprecated top-level
onKeyPress; useonKeyDown. NativecontrolProps.onKeyPressremains available for temporary compatibility.
Popover
- Remove the legacy component and its types from
/legacy; use the current root component.
Popup
- Remove
anchorRef; keep the anchor DOM node in state and pass it throughanchorElement. - Remove
onClose,onEscapeKeyDown, andonOutsideClick; useonOpenChange(open, event, reason). - Remove
PopupAnchorRefandPopupCloseReason; usePopupAnchorElementandOpenChangeReason. Apply these replacements to legacy DropdownMenu popup props and component defaults too.
Progress
- Remove
margin: 0 auto; position or center the component through application layout.
Select
- Render options through the new List, with updated rows, group headers, DOM roles, IDs, and CSS classes.
- Remove
virtualizationThreshold; wrap Select inListVirtualizerto virtualize. Without the wrapper, every option renders, and formerly virtualized popups may become as wide as their widest option;popupWidth="fit"also fits the control. - Support non-string option values. Use
getValueKeyfor object values; the value and update types follow the option type. Keys must be unique across the entire list, including groups. - Remove option
text; usegetOptionTextfor display and search text. - Replace
renderSelectedOption(option, index)withrenderSelectedOptions(options), called once for the whole selection. - Rename option types
SelectOption/SelectOptionGrouptoSelectOptionProps/SelectOptionGroupProps, and componentsSelectItem/SelectItemGrouptoSelectOption/SelectOptionGroup, without compatibility aliases. - Remove the top-level
valueandonKeyDownarguments ofrenderFilter; read them frominputPropsand forward the combobox wiring to the input.onChangeremains available. - Always provide
isItemActiveto custom option renderers, and provideselectedtorenderOption. AddselectionStyle="none"for custom selection indication; row-height estimates follow the new geometry. - Anchor the popup to the control through the new
g-select__anchorwrapper. Increase its default trigger offset from 1px to 4px; outside error messages are covered while it is open. - Use
labelas the accessible trigger name and the mobile sheet title. The built-in filter has thecomboboxrole, and typeahead matches a prefix. - Render rounded rows with updated padding, active backgrounds, and group-header typography. Mobile rows become 44px tall.
- Remove vertical control padding and stop clipping tall selected content.
- Do not count empty values without matching options as selected; an option with empty text hides the placeholder.
- Fire mobile close callbacks when closing starts. Controlled sheets wait for
open=false, and controlled filters are no longer reset on close. - Remove the deprecated
errorprop; usevalidationStateanderrorMessage.
Sheet
- Replace
visiblewith optionalopen; adddefaultOpenfor an initially open uncontrolled sheet. - Determine controlled mode from
open, rather than the presence ofonOpenChange. A controlled sheet closes when its parent updatesopen; an uncontrolled sheet closes itself. - Remove
onClose; useonOpenChangefor dismissal andonTransitionOutCompletefor cleanup after animation.
Switch
- Use the
body-1font variant for sizel.
Table and TableColumnSetup
- Move Table, TableColumnSetup, related types, and
withTableActions,withTableCopy,withTableSelection,withTableSettings, andwithTableSortingto/legacy; mark them deprecated. Future table development continues in@gravity-ui/table. - Keep the existing table API and table CSS block names. Row actions now use
g-menu-legacy; column-settings internals use legacy tree/list class names without the old size and radius modifiers. - Increase the column-settings popup offset from 1px to 4px.
- Preserve translation keysets and restore TableColumnSetup defaults from
DefaultPropsProvider.
Tabs
- Remove the legacy component and its related exports from
/legacy; useTabList,Tab,TabProvider, andTabPanelfrom the root entry point.
TextInput, PasswordInput, and TextArea
- Remove
error; usevalidationState="invalid"anderrorMessage. - Remove top-level
onKeyPress; useonKeyDown, accounting for non-character keys and IME composition. NativecontrolProps.onKeyPressremains available for temporary compatibility.
Toast
- Wrap long words.
- Move the background pseudo-element from
.g-toast__container::beforeto.g-toast::beforeand remove rootoverflow: hidden.
Tooltip and ActionTooltip
- Share the open delay under
Provider, including ClipboardButton tooltips. Only one tooltip is open at a time; moving to another during the 300ms warm window opens it instantly. - Configure that window through
defaultProps.TooltipDelayGroup.skipDelay. Keyboard-focus opening remains instant.
TreeList and TreeSelect
- Remove the experimental tree components from
/unstable; migrate toUIKitNormalizedListandUIKitNormalizedSelectfrom@gravity-ui/normalized-list/uikit. - Update CSS to the
g-nl-namespace and Select QA constants toNormalizedSelectQa. Render mobile sheets throughrenderPopupwhen migrating to UIKitNormalizedSelect.
Layout primitives
Box and Card
- Remove
spacingobjects; use explicit logical margin and padding props withspacing-*tokens. - Add responsive Box style props for dimensions, positioning, flex/grid placement, spacing, colors, borders, and radii. Explicit
stylevalues override generated props. - Stop enforcing
box-sizing: border-boxin Box. - Infer native HTML props from
asat component call sites. Interfaces extending layout prop types must declare native attributes explicitly.
Flex
- Add responsive style props and native CSS gaps. Numeric gaps now mean pixels; design-system spacing uses
spacing-*tokens. - Replace
grow,basis, andshrinkwithflexGrow,flexBasis, andflexShrink; replacegapRowwithrowGap, andspacewithgap. - Remove
centerContent; setjustifyContentandalignItems. Remove ineffectivejustifyItems. - Stop wrapping children for
spaceand stop enforcingborder-box; review wrapper selectors and fixed-size layouts.
Grid
- Add a CSS Grid primitive with responsive tracks, areas, auto-placement, alignment, and gaps, plus Box style props.
- Export the CSS track helpers
repeat,minmax, andfitContent.
Container
- Replace breakpoint-based
maxWidthwithsize;maxWidthnow accepts CSS dimensions. - Keep
gutters, but interpret numbers as pixels and support responsive CSS values and spacing tokens. Replacegutters={false}withgutters={0}. - Replace
spaceRowwithrowGap, including layout-theme configuration. Apply spacing only between adjacent direct-child Row elements. - Base Container on Box rather than Flex; remove flex alignment and gap behavior for arbitrary children, and leave box sizing to application CSS.
Row
- Use CSS Grid with 12 tracks and native gaps instead of negative margins and column padding.
- Replace
space/spaceRowwithgaporcolumnGap/rowGap; use spacing tokens for previous scale values. - Accept Box style props, polymorphic elements, refs, and Grid alignment props. Track alignment replaces Flex alignment behavior.
Col
- Remove breakpoint props
s,m,l,xl, andxxl; move sizes intosizemaps or tuples. - Let unsized columns span all 12 tracks instead of sharing remaining space. Sized columns take their width from a parent Row.
- Apply backgrounds and borders to the content box instead of gutter padding. Flex sizing no longer affects columns inside Row.
Hooks and utilities
useColorGenerator
- Remove the deprecated
themeoption; read the current theme from ThemeProvider.
useDropZone
- Promote
unstable_useDropZoneand its related types to the root entry point asuseDropZone; remove the/unstableexports.
useList family
- Remove the previous experimental
useListfamily and its related containers, row views, types, and utilities from/unstable. - Migrate to
@gravity-ui/normalized-list, includinguseNormalizedListand the corresponding UIKit adapters; use a version compatible with UIKit v8.
configure, getConfig, Lang, and Platform
- Create a new configuration object on each
configurecall. CallgetConfig()again instead of relying on a saved object to reflect later changes. - Replace the Lang and Platform TypeScript enums with const objects and union types. Value access such as
Lang.Ruremains; usetypeof Lang.Ruor a literal in type positions.
LayerManager
- Remove deprecated
meta.layersCountfromlayerschangeevents; usemeta.layers.length.getLayersCount()remains available.
Package entry points and styles
Dependencies and exports
- Require React, React DOM, and applicable React types for versions 18 or 19.
- Add
/virtualizerwithVirtualizerandListVirtualizer; move ListVirtualizer out of/unstable. Install its optional peer@tanstack/react-virtualexplicitly. - Add
/hello-pangea-dndwithListHelloPangeaDnd, row/handle helpers, anduseListHelloPangeaDndfor list reordering, including virtualized lists and transformed overlay containers. Rename the hook options type toUseListHelloPangeaDndPropsand install@hello-pangea/dndexplicitly. - Make
@hello-pangea/dnd,react-window, andreact-virtualized-auto-sizeroptional peers required by every/legacyimport. - Keep
/unstableas an empty entry point for future experiments. - Replace the lodash dependency with
es-toolkit. - Extend
KeysetswithHelloPangeaDndandFileDropZone; custom language keysets must supply their keys.
Themes, typography, and global styles
- Generate theme variables with
@gravity-ui/uikit-themerv2 and preserve generated theme CSS in the published build. - Remove the SCSS
styles/themesmodule and itsg-theme-*mixins. Regenerate custom themes with v2. - Replace
--g-color-base-light*with contrast-light tokens; the old disabled background uses--g-color-base-contrast-light-simple-hover, and the accent-disabled opacity changes from 30% to 7% in default themes. - Add semantic background and line palettes for
contrast,contrast-inverted,contrast-light, andcontrast-dark. Add corresponding solid black/white palette steps in both default themes. - Update default color values and their
rgb(r g b / a)serialization, including the dark infographics tooltip background. Review visual baselines and literal-value snapshots. - Introduce
--g-text-{group}-accent-font-weight; deprecate--g-text-accent-font-weight, whose overrides no longer affect Breadcrumbs and Menu. - Rename multi-x size and breakpoint names to
2xs,2xl, and3xl, including responsive maps, active-media-query values, and CSS modifiers. Breakpoint widths stay unchanged. - Apply hover styling only under
@media (hover: hover). - Extend
button-resetto reset margin, appearance, selection, touch action, and tap highlight. Stop removing the native focus outline.
Upgrading
Start with the v8 migration checklist, then follow the dedicated List, Select, and layout guides for the APIs you use.