diff --git a/src/components/LoadingOverlay/LoadingOverlay.scss b/src/components/LoadingOverlay/LoadingOverlay.scss
new file mode 100644
index 0000000000..bf83f8ff5a
--- /dev/null
+++ b/src/components/LoadingOverlay/LoadingOverlay.scss
@@ -0,0 +1,46 @@
+@use '../variables';
+
+$block: '.#{variables.$ns}loading-overlay';
+
+#{$block} {
+ position: relative;
+
+ &__overlay {
+ position: absolute;
+ z-index: 200;
+ inset: 0;
+
+ display: flex;
+ visibility: hidden;
+ justify-content: center;
+ align-items: center;
+
+ opacity: 0;
+
+ transition:
+ visibility 0.1s linear,
+ opacity 0.1s linear;
+
+ &_visible {
+ visibility: visible;
+ opacity: 1;
+ }
+ }
+
+ &__background {
+ position: absolute;
+ inset: 0;
+
+ opacity: 80%;
+
+ &_type {
+ &_base {
+ background-color: var(--g-color-base-background);
+ }
+
+ &_float {
+ background-color: var(--g-color-base-float);
+ }
+ }
+ }
+}
diff --git a/src/components/LoadingOverlay/LoadingOverlay.tsx b/src/components/LoadingOverlay/LoadingOverlay.tsx
new file mode 100644
index 0000000000..5c18f7cbc5
--- /dev/null
+++ b/src/components/LoadingOverlay/LoadingOverlay.tsx
@@ -0,0 +1,42 @@
+import React from 'react';
+
+import {Loader} from '../Loader';
+import type {LoaderProps} from '../Loader';
+import {Box} from '../layout';
+import type {BoxProps} from '../layout';
+import {block} from '../utils/cn';
+
+import './LoadingOverlay.scss';
+
+const b = block('loading-overlay');
+
+export type OverlayBackground = 'base' | 'float';
+
+export interface LoadingOverlayProps extends BoxProps {
+ loaderProps?: LoaderProps;
+ background?: OverlayBackground;
+ loading?: boolean;
+ children?: React.ReactNode;
+ className?: string;
+ contentClassName?: string;
+}
+
+export function LoadingOverlay({
+ loaderProps,
+ background = 'base',
+ loading = false,
+ children,
+ className,
+ contentClassName,
+ ...boxProps
+}: LoadingOverlayProps) {
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/components/LoadingOverlay/README.md b/src/components/LoadingOverlay/README.md
new file mode 100644
index 0000000000..455caefe4f
--- /dev/null
+++ b/src/components/LoadingOverlay/README.md
@@ -0,0 +1,32 @@
+
+
+# Loader
+
+
+
+```tsx
+import {LoadingOverlay} from '@gravity-ui/uikit';
+```
+
+The `LoadingOverlay` component renders an overlay with a loader over the content. It can be used to preserve the desired layout while loading data.
+
+### PropTypes
+
+| Name | Type | Required | Default | Description |
+| :--------------- | :----------------- | :------: | :------ | :------------------------------------------ |
+| className | `String` | | | CSS class name of root element |
+| contentClassName | `String` | | | CSS class name of a content wrapper element |
+| loading | `Boolean` | | `false` | Overlay visibility state |
+| background | `"base"` `"float"` | | `base` | Background style |
+| loaderProps | `LoaderProps` | | | Props of a Loader element |
+| children | `React.ReactNode` | | | Content |
+| ...props | `BoxProps` | | | Props of a wrapping Box element |
+
+### Basic usage
+
+```jsx
+
+ I am an example
+ content
+
+```
diff --git a/src/components/LoadingOverlay/__stories__/LoadingOverlay.scss b/src/components/LoadingOverlay/__stories__/LoadingOverlay.scss
new file mode 100644
index 0000000000..d68344ee0a
--- /dev/null
+++ b/src/components/LoadingOverlay/__stories__/LoadingOverlay.scss
@@ -0,0 +1,11 @@
+@use '../../variables';
+
+$block: '.#{variables.$ns}loading-overlay-showcase';
+
+#{$block} {
+ width: fit-content;
+
+ &__content {
+ padding: var(--g-spacing-1);
+ }
+}
diff --git a/src/components/LoadingOverlay/__stories__/LoadingOverlay.stories.tsx b/src/components/LoadingOverlay/__stories__/LoadingOverlay.stories.tsx
new file mode 100644
index 0000000000..efb734e50a
--- /dev/null
+++ b/src/components/LoadingOverlay/__stories__/LoadingOverlay.stories.tsx
@@ -0,0 +1,69 @@
+import React from 'react';
+
+import type {Meta, StoryFn} from '@storybook/react';
+
+import {Button} from '../../Button';
+import {spacing} from '../../layout';
+import {block} from '../../utils/cn';
+import {LoadingOverlay} from '../LoadingOverlay';
+import type {LoadingOverlayProps} from '../LoadingOverlay';
+
+import './LoadingOverlay.scss';
+
+const b = block('loading-overlay-showcase');
+
+export default {
+ title: 'Components/Feedback/LoadingOverlay',
+ component: LoadingOverlay,
+} as Meta;
+
+const DefaultTemplate: StoryFn = (args) => {
+ const [showContent, setShowContent] = React.useState(true);
+
+ return (
+
+
+ {showContent && (
+
+ I am an example
+ content
+
+ )}
+
+
+
+ );
+};
+export const Default = DefaultTemplate.bind({});
+
+Default.args = {
+ loading: true,
+};
+
+const BackgroundTemplate: StoryFn = (args) => {
+ return (
+
+
+
+ I am an example
+ content
+
+
+
+
+
+ I am an example
+ content
+
+
+
+ );
+};
+
+export const Background = BackgroundTemplate.bind({});
+
+Background.args = {
+ loading: true,
+};
diff --git a/src/components/LoadingOverlay/index.ts b/src/components/LoadingOverlay/index.ts
new file mode 100644
index 0000000000..2453ce63f3
--- /dev/null
+++ b/src/components/LoadingOverlay/index.ts
@@ -0,0 +1 @@
+export * from './LoadingOverlay';
diff --git a/src/components/index.ts b/src/components/index.ts
index 34146e1cf1..c0f9839f50 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -22,6 +22,7 @@ export * from './Label';
export * from './Link';
export * from './List';
export * from './Loader';
+export * from './LoadingOverlay';
export * from './Menu';
export * from './Modal';
export * from './Pagination';