Skip to content

v8.0.0

Latest

Choose a tag to compare

@gravity-ui gravity-ui released this 23 Oct 15:23
02ea972

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: Provider combines 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. Menu supports composable items and submenus.
  • Responsive layouts: new Grid and responsive style props for Box, Flex, Container, Row, and Col.
  • Stable APIs: ColorPicker, FileDropZone, and useDropZone move 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: Button gains contrast, contrast-inverted, contrast-light, and contrast-dark views, 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.

Dependency guide

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.

Provider migration

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.

Entry point migration

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.

Select migration

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 ThemeProvider and ThemeProviderProps to theme and direction. Move lang/fallbackLang to LangProvider, layout to LayoutProvider, and defaultProps to DefaultPropsProvider; Provider accepts them together.
  • Export LangProvider and LayoutProvider for 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 Provider accept mobile settings directly. Nested Provider instances use independent mobile and router defaults, so pass those settings explicitly when needed.
  • Remove __experimentalMobileModals from providers and the mobile context. Enable mobile Modal and Dialog rendering whenever mobile is enabled.

ActionsPanel

  • Use the stable Menu for overflow actions and submenus.
  • Rename ActionsPanelItem.dropdown to menu; its item now accepts MenuItemProps. Replace text with children, action with onClick, iconStart with icon, and iconEnd with arrow.
  • Replace nested items arrays with child Menu components. Pass native props directly instead of through extraProps, 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 with alt="".

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/Breadcrumbs to Breadcrumbs. Existing Breadcrumbs.label_more overrides continue to work.

Button

  • Remove extraProps; pass native button, link, or custom-component props directly. This also applies to APIs based on ButtonProps, including alert actions, menu triggers, ActionsPanel buttons, and Dialog footer buttons.
  • Remove Button.Icon physical side values left and right; use start and end for direction-aware positioning.
  • Add contrast, contrast-inverted, contrast-light, and contrast-dark views. Remove normal-contrast, outlined-contrast, and flat-contrast; replace normal-contrast with contrast-light, and use the CSS API for custom outlined or flat contrast buttons.

Checkbox, Radio, and RadioGroup

  • Use body-1 typography for size l; increase the Checkbox and Radio indicator to 18px at that size.
  • Use an 18px label line height for sizes s and m, and align indicators with the first label line.
  • Update RadioGroup option spacing: horizontal gaps are 16px for m/l and 20px for xl; vertical xl gaps become 16px.
  • Draw the radio dot on .g-radio__disc instead of its ::before pseudo-element. Use a 1px focus-outline offset.

ClipboardButton

  • Add tooltipProps for supported ActionTooltip settings, including placement, offset, portal behavior, disabled state, DOM props, QA props, and onOpenChange.
  • Participate in the shared tooltip delay group under Provider.

ColorPicker

  • Promote unstable_ColorPicker and its props type to ColorPicker and ColorPickerProps in the root entry point. Remove their /unstable exports.

Dialog

  • Remove onClose, onEscapeKeyDown, onOutsideClick, and onEnterKeyDown. Handle dismissal through onOpenChange; use initialFocus="apply" or form submission for Enter actions.
  • Remove size; use maxWidth and fullWidth for 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-close class.
  • Stop stretching desktop footer buttons and remove their 128px minimum width. Configure propsButtonApply/propsButtonCancel to restore custom sizing; mobile buttons still stretch.
  • Use mobile rendering by default in mobile context.

Disclosure

  • Remove physical arrowPosition values left and right; use start and end.

FileDropZone

  • Promote unstable_FileDropZone to FileDropZone in the root entry point, together with its related types. Remove the old /unstable exports.
  • Include the FileDropZone keyset in the public Keysets type.

HelpMark and DefinitionList

  • Rename HelpMark.iconSize to size, including component defaults and DefinitionList note objects. Supported values and the default remain unchanged.

Label

  • Rename size="xxs" to size="2xs" and .g-label_size_xxs to .g-label_size_2xs.

Link

  • Remove extraProps; pass native anchor props directly.
  • Moving target="_blank" to the root adds rel="noopener noreferrer" when rel is not supplied. Review native props that previously could be overridden inside extraProps.

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 block g-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, and xl. List, Select, and Menu rows follow this geometry.
  • Derive padding and header heights from the row height. Use --g-list-item-view-min-height and 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, and MenuDivider.
  • Use MenuItem children and a trigger, or inline, 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* to g-menu*; legacy blocks become g-menu-legacy and g-dropdown-menu-legacy. Update Tabs overflow-menu selectors too.
  • Use MenuLegacy for legacy Menu defaults in DefaultPropsProvider; the DropdownMenu key remains unchanged.

Modal

  • Remove onClose, onEscapeKeyDown, onOutsideClick, and onEnterKeyDown; use onOpenChange for dismissal and native keyboard or form handling for Enter actions.
  • Replace ModalCloseReason with the public OpenChangeReason type. Escape and outside dismissal reasons become escape-key and outside-press.
  • Remove automatic content-height animations and disableHeightTransition.
  • Use mobile rendering by default in mobile context.

NumberInput

  • Remove the deprecated top-level onKeyPress; use onKeyDown. Native controlProps.onKeyPress remains 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 through anchorElement.
  • Remove onClose, onEscapeKeyDown, and onOutsideClick; use onOpenChange(open, event, reason).
  • Remove PopupAnchorRef and PopupCloseReason; use PopupAnchorElement and OpenChangeReason. 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 in ListVirtualizer to 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 getValueKey for object values; the value and update types follow the option type. Keys must be unique across the entire list, including groups.
  • Remove option text; use getOptionText for display and search text.
  • Replace renderSelectedOption(option, index) with renderSelectedOptions(options), called once for the whole selection.
  • Rename option types SelectOption/SelectOptionGroup to SelectOptionProps/SelectOptionGroupProps, and components SelectItem/SelectItemGroup to SelectOption/SelectOptionGroup, without compatibility aliases.
  • Remove the top-level value and onKeyDown arguments of renderFilter; read them from inputProps and forward the combobox wiring to the input. onChange remains available.
  • Always provide isItemActive to custom option renderers, and provide selected to renderOption. Add selectionStyle="none" for custom selection indication; row-height estimates follow the new geometry.
  • Anchor the popup to the control through the new g-select__anchor wrapper. Increase its default trigger offset from 1px to 4px; outside error messages are covered while it is open.
  • Use label as the accessible trigger name and the mobile sheet title. The built-in filter has the combobox role, 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 error prop; use validationState and errorMessage.

Sheet

  • Replace visible with optional open; add defaultOpen for an initially open uncontrolled sheet.
  • Determine controlled mode from open, rather than the presence of onOpenChange. A controlled sheet closes when its parent updates open; an uncontrolled sheet closes itself.
  • Remove onClose; use onOpenChange for dismissal and onTransitionOutComplete for cleanup after animation.

Switch

  • Use the body-1 font variant for size l.

Table and TableColumnSetup

  • Move Table, TableColumnSetup, related types, and withTableActions, withTableCopy, withTableSelection, withTableSettings, and withTableSorting to /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; use TabList, Tab, TabProvider, and TabPanel from the root entry point.

TextInput, PasswordInput, and TextArea

  • Remove error; use validationState="invalid" and errorMessage.
  • Remove top-level onKeyPress; use onKeyDown, accounting for non-character keys and IME composition. Native controlProps.onKeyPress remains available for temporary compatibility.

Toast

  • Wrap long words.
  • Move the background pseudo-element from .g-toast__container::before to .g-toast::before and remove root overflow: 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 to UIKitNormalizedList and UIKitNormalizedSelect from @gravity-ui/normalized-list/uikit.
  • Update CSS to the g-nl- namespace and Select QA constants to NormalizedSelectQa. Render mobile sheets through renderPopup when migrating to UIKitNormalizedSelect.

Layout primitives

Box and Card

  • Remove spacing objects; use explicit logical margin and padding props with spacing-* tokens.
  • Add responsive Box style props for dimensions, positioning, flex/grid placement, spacing, colors, borders, and radii. Explicit style values override generated props.
  • Stop enforcing box-sizing: border-box in Box.
  • Infer native HTML props from as at 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, and shrink with flexGrow, flexBasis, and flexShrink; replace gapRow with rowGap, and space with gap.
  • Remove centerContent; set justifyContent and alignItems. Remove ineffective justifyItems.
  • Stop wrapping children for space and stop enforcing border-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, and fitContent.

Container

  • Replace breakpoint-based maxWidth with size; maxWidth now accepts CSS dimensions.
  • Keep gutters, but interpret numbers as pixels and support responsive CSS values and spacing tokens. Replace gutters={false} with gutters={0}.
  • Replace spaceRow with rowGap, 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/spaceRow with gap or columnGap/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, and xxl; move sizes into size maps 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 theme option; read the current theme from ThemeProvider.

useDropZone

  • Promote unstable_useDropZone and its related types to the root entry point as useDropZone; remove the /unstable exports.

useList family

  • Remove the previous experimental useList family and its related containers, row views, types, and utilities from /unstable.
  • Migrate to @gravity-ui/normalized-list, including useNormalizedList and the corresponding UIKit adapters; use a version compatible with UIKit v8.

configure, getConfig, Lang, and Platform

  • Create a new configuration object on each configure call. Call getConfig() 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.Ru remains; use typeof Lang.Ru or a literal in type positions.

LayerManager

  • Remove deprecated meta.layersCount from layerschange events; use meta.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 /virtualizer with Virtualizer and ListVirtualizer; move ListVirtualizer out of /unstable. Install its optional peer @tanstack/react-virtual explicitly.
  • Add /hello-pangea-dnd with ListHelloPangeaDnd, row/handle helpers, and useListHelloPangeaDnd for list reordering, including virtualized lists and transformed overlay containers. Rename the hook options type to UseListHelloPangeaDndProps and install @hello-pangea/dnd explicitly.
  • Make @hello-pangea/dnd, react-window, and react-virtualized-auto-sizer optional peers required by every /legacy import.
  • Keep /unstable as an empty entry point for future experiments.
  • Replace the lodash dependency with es-toolkit.
  • Extend Keysets with HelloPangeaDnd and FileDropZone; custom language keysets must supply their keys.

Themes, typography, and global styles

  • Generate theme variables with @gravity-ui/uikit-themer v2 and preserve generated theme CSS in the published build.
  • Remove the SCSS styles/themes module and its g-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, and contrast-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, and 3xl, including responsive maps, active-media-query values, and CSS modifiers. Breakpoint widths stay unchanged.
  • Apply hover styling only under @media (hover: hover).
  • Extend button-reset to 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.