diff --git a/.storybook/decorators/withLang.tsx b/.storybook/decorators/withLang.tsx deleted file mode 100644 index aa306c8f..00000000 --- a/.storybook/decorators/withLang.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; - -import {settings} from '@gravity-ui/date-utils'; -import {configure} from '@gravity-ui/uikit'; -import type {Decorator} from '@storybook/react'; - -export const withLang: Decorator = (Story, context) => { - const lang = context.globals.lang; - configure({lang}); - - // eslint-disable-next-line react-hooks/rules-of-hooks - React.useEffect(() => { - (async () => { - await settings.loadLocale(lang); - settings.setLocale(lang); - })(); - }, [lang]); - - return ; -}; diff --git a/.storybook/decorators/withMobile.tsx b/.storybook/decorators/withMobile.tsx deleted file mode 100644 index 85e79767..00000000 --- a/.storybook/decorators/withMobile.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import {MobileProvider} from '@gravity-ui/uikit'; -import type {Decorator} from '@storybook/react'; - -export const withMobile: Decorator = (Story, context) => { - const platform = context.globals.platform; - - return ( - - - - ); -}; diff --git a/.storybook/decorators/withProvider.tsx b/.storybook/decorators/withProvider.tsx new file mode 100644 index 00000000..aa12a0f2 --- /dev/null +++ b/.storybook/decorators/withProvider.tsx @@ -0,0 +1,32 @@ +import * as React from 'react'; + +import {settings} from '@gravity-ui/date-utils'; +import {Provider, configure} from '@gravity-ui/uikit'; +import type {Decorator} from '@storybook/react'; + +export const withProvider: Decorator = (Story, context) => { + const lang = context.globals.lang; + + configure({lang}); + + // eslint-disable-next-line react-hooks/rules-of-hooks + React.useEffect(() => { + (async () => { + await settings.loadLocale(lang); + settings.setLocale(lang); + })(); + }, [lang]); + + return ( + + + + ); +}; diff --git a/.storybook/decorators/withTheme.tsx b/.storybook/decorators/withTheme.tsx deleted file mode 100644 index 09c2da20..00000000 --- a/.storybook/decorators/withTheme.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import {ThemeProvider} from '@gravity-ui/uikit'; -import type {Decorator} from '@storybook/react'; - -export const withTheme: Decorator = (Story, context) => { - return ( - - - - ); -}; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index a4fbc00c..da5e5b93 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -6,13 +6,11 @@ import '@gravity-ui/uikit/styles/styles.css'; import {MINIMAL_VIEWPORTS} from '@storybook/addon-viewport'; import type {Preview} from '@storybook/react'; -import {withLang} from './decorators/withLang'; -import {withMobile} from './decorators/withMobile'; +import {withProvider} from './decorators/withProvider'; import {withStrictMode} from './decorators/withStrictMode'; -import {withTheme} from './decorators/withTheme'; const preview: Preview = { - decorators: [withLang, withMobile, withTheme, withStrictMode], + decorators: [withProvider, withStrictMode], parameters: { jsx: {showFunctions: true}, viewport: { diff --git a/README.md b/README.md index 53ec534c..bbfe6aed 100644 --- a/README.md +++ b/README.md @@ -10,25 +10,38 @@ npm install @gravity-ui/components ## Usage -`@gravity-ui/uikit` is a peer dependency: install it, import its styles once at the app entry point, and wrap the app in `ThemeProvider`. The components in this package render unstyled without that setup. +`@gravity-ui/uikit` 8 and React 18/19 are required. Install the current UIKit 8 prerelease with `npm install @gravity-ui/uikit@beta`. + +`@gravity-ui/uikit` is a peer dependency: install it, import its styles once at the app entry point, and wrap the app in `Provider`. The components in this package render unstyled without that setup. ```tsx -import {ThemeProvider, TextInput} from '@gravity-ui/uikit'; +import {Provider, TextInput} from '@gravity-ui/uikit'; import {FormRow} from '@gravity-ui/components'; import '@gravity-ui/uikit/styles/fonts.css'; import '@gravity-ui/uikit/styles/styles.css'; export function App() { return ( - + - + ); } ``` +### Migrating to UIKit 8 + +- Replace the application-level `ThemeProvider` with `Provider`. +- Use `onOpenChange` instead of `onClose` in `ConfirmDialog` and `ChangelogDialog`. `ConfirmDialog` accepts the new Dialog props, including `maxWidth` and `fullWidth` instead of `size`. +- Remove `disableHeightTransition` from `ChangelogDialog` and cookie consent popup settings; UIKit no longer animates content height. +- `Stories` and `StoriesGroup` keep `onClose`, with optional event/reason arguments and UIKit 8 reasons (`escape-key`, `outside-press`, `click`). +- Remove `moreControlProps.virtualizationThreshold` from `AdaptiveTabs`; its dropdowns use `ListVirtualizer`. +- Pass native HTML attributes directly to button/link props, including `StoreBadge`, instead of `extraProps`. Use UIKit 8 Button views in custom story actions. + +See the [UIKit 8 migration guide](https://github.com/gravity-ui/uikit/blob/next/docs/migration-to-v8.md) for the underlying API changes. This package uses the new List, Menu, and Popover APIs without the legacy entry point. + ### Confirmation dialog ```tsx @@ -42,7 +55,7 @@ import {ConfirmDialog} from '@gravity-ui/components'; textButtonCancel="Cancel" onClickButtonApply={handleDelete} onClickButtonCancel={() => setOpen(false)} - onClose={() => setOpen(false)} + onOpenChange={setOpen} />; ``` @@ -97,7 +110,7 @@ The composite-component layer of Gravity UI — ready-made form rows, confirmati ### Common pitfalls -- **Nothing is styled without uikit setup.** Install `@gravity-ui/uikit`, import `@gravity-ui/uikit/styles/styles.css` (plus `fonts.css`) once, and wrap the app in `ThemeProvider` — this package ships no global styles of its own. +- **Nothing is styled without uikit setup.** Install `@gravity-ui/uikit`, import `@gravity-ui/uikit/styles/styles.css` (plus `fonts.css`) once, and wrap the app in `Provider` — this package ships no global styles of its own. - **`FormRow` does not render the input.** Pass the control as `children` and link it with `fieldId` matching the control's `id`; the `label` prop is the label text, not a `