= (inProps: HeaderLogoProps) => {
+ const { children, className, classes: inClasses, ...props } = useThemeProps({ props: inProps, name: 'ESHeaderLogo' });
+
+ const ownerState = { classes: inClasses };
+ const classes = useUtilityClasses(ownerState);
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/packages/react/src/components/Header/HeaderLogo/HeaderLogo.types.ts b/packages/react/src/components/Header/HeaderLogo/HeaderLogo.types.ts
new file mode 100644
index 000000000..c99ae0ec8
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderLogo/HeaderLogo.types.ts
@@ -0,0 +1,26 @@
+/* eslint-disable @typescript-eslint/no-empty-object-type */
+
+import { ReactNode } from 'react';
+
+import { HeaderLogoClasses } from './HeaderLogo.classes';
+
+import { SxProps, Theme } from '@mui/material';
+import { OverrideProps } from '@mui/material/OverridableComponent';
+
+export interface HeaderLogoTypeMap {
+ props: P & {
+ children?: ReactNode;
+ /** Override or extend the styles applied to the component. */
+ classes?: Partial;
+ /** Class applied to the root element. */
+ className?: string;
+ /** The system prop that allows defining system overrides as well as additional CSS styles. */
+ sx?: SxProps;
+ };
+ defaultComponent: D;
+}
+
+export type HeaderLogoProps<
+ D extends React.ElementType = HeaderLogoTypeMap['defaultComponent'],
+ P = {},
+> = OverrideProps, D>;
diff --git a/packages/react/src/components/Header/HeaderLogo/index.ts b/packages/react/src/components/Header/HeaderLogo/index.ts
new file mode 100644
index 000000000..8c9a8b49e
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderLogo/index.ts
@@ -0,0 +1,3 @@
+export { HeaderLogo } from './HeaderLogo';
+export { HeaderLogoClasses, headerLogoClasses, HeaderLogoClassKey } from './HeaderLogo.classes';
+export { HeaderLogoProps, HeaderLogoTypeMap } from './HeaderLogo.types';
diff --git a/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.api.mdx b/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.api.mdx
new file mode 100644
index 000000000..434ba9925
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.api.mdx
@@ -0,0 +1,37 @@
+import { Meta } from '@storybook/blocks';
+import LinkTo from '@storybook/addon-links/react';
+import { TableInterface } from '~storybook/components/TableInterface';
+
+
+
+# HeaderNavigation API
+
+```js
+import { HeaderNavigation } from '@esfront/react';
+```
+
+## Component name
+
+The name `ESHeaderNavigation` can be used when providing default props in the theme.
+
+## Props
+
+
+
+
+
+## CSS
+
+
+
+
+
+## Demos
+
+
diff --git a/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.classes.ts b/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.classes.ts
new file mode 100644
index 000000000..72d268383
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.classes.ts
@@ -0,0 +1,18 @@
+import { generateUtilityClass, generateUtilityClasses } from '@mui/material';
+
+export type HeaderNavigationClasses = {
+ /** Styles applied to the root element. */
+ root: string;
+ /** Styles applied to the button element. */
+ button: string;
+};
+export type HeaderNavigationClassKey = keyof HeaderNavigationClasses;
+
+export function getHeaderNavigationUtilityClass(slot: string): string {
+ return generateUtilityClass('ESHeaderNavigation', slot);
+}
+
+export const headerNavigationClasses: HeaderNavigationClasses = generateUtilityClasses('ESHeaderNavigation', [
+ 'root',
+ 'button',
+]);
diff --git a/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.tsx b/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.tsx
new file mode 100644
index 000000000..a3dcb78ec
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.tsx
@@ -0,0 +1,154 @@
+import { Children, isValidElement, useRef, useState } from 'react';
+
+import { HeaderNavigationProps } from './HeaderNavigation.types';
+
+import clsx from 'clsx';
+import { getHeaderNavigationUtilityClass, headerNavigationClasses } from './HeaderNavigation.classes';
+
+import { unstable_composeClasses as composeClasses } from '@mui/base';
+
+import { styled, useThemeProps } from '@mui/material/styles';
+import { Menu } from '@mui/material';
+import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
+
+import { useMenu, useResizeObserver } from '../../../hooks';
+import { IconChevronDownW200 } from '../../../icons';
+import { Button } from '../../Button';
+import { MenuItem } from '../../MenuItem';
+
+type HeaderNavigationOwnerState = {
+ classes?: HeaderNavigationProps['classes'];
+};
+
+const useUtilityClasses = (ownerState: HeaderNavigationOwnerState) => {
+ const { classes } = ownerState;
+
+ const slots = {
+ root: ['root'],
+ button: ['button'],
+ };
+
+ return composeClasses(slots, getHeaderNavigationUtilityClass, classes);
+};
+
+const HeaderNavigationRoot = styled('nav', {
+ name: 'ESHeaderNavigation',
+ slot: 'Root',
+ overridesResolver: (props, styles) => styles.root,
+})({
+ display: 'flex',
+ gap: '4px',
+ position: 'relative',
+ flexGrow: 1,
+
+ [`.ESButton-root`]: {
+ whiteSpace: 'nowrap',
+ flexShrink: 0,
+ },
+});
+
+const HeaderNavigationButton = styled(Button, {
+ name: 'ESChips',
+ slot: 'Button',
+ overridesResolver: (_props, styles) => styles.button,
+})({});
+
+export const HeaderNavigation = (inProps: HeaderNavigationProps) => {
+ const { children, className, sx, ...props } = useThemeProps({ props: inProps, name: 'ESHeaderNavigation' });
+
+ const ref = useRef(null);
+ const [anchorEl, onMenuClick, onMenuClose] = useMenu();
+
+ const [lastIndex, setLastIndex] = useState(Children.count(children) - 1);
+
+ const onResize = () => {
+ if (typeof window !== 'undefined' && ref.current) {
+ let width = 0;
+
+ const nodes = ref.current.querySelectorAll(`& > *:not(.${headerNavigationClasses.button})`);
+ const button = ref.current.querySelector(`.${headerNavigationClasses.button}`);
+
+ const containerWidth = ref.current.getBoundingClientRect().width;
+ const columnGap = parseInt(window.getComputedStyle(ref.current).columnGap);
+
+ nodes.forEach((item) => {
+ (item as HTMLElement).style.display = 'inline-flex';
+ width += (item as HTMLElement).getBoundingClientRect().width + columnGap;
+ });
+
+ if (width > containerWidth) {
+ width += (button as HTMLElement).getBoundingClientRect().width;
+ }
+
+ let i = nodes.length - 1;
+
+ while (width > containerWidth && i > 0) {
+ width -= (nodes[i] as HTMLElement).getBoundingClientRect().width;
+ i--;
+ }
+
+ for (let j = i + 1; j < nodes.length; j++) {
+ (nodes[j] as HTMLElement).style.display = 'none';
+ }
+
+ onMenuClose();
+ setLastIndex(i);
+ }
+ };
+
+ const ownerState = { ...props };
+ const classes = useUtilityClasses(ownerState);
+
+ useResizeObserver(ref, onResize);
+
+ useEnhancedEffect(() => {
+ onResize();
+ }, []);
+
+ return (
+ <>
+
+ {children}
+ }
+ size="300"
+ style={{ display: lastIndex < Children.count(children) - 1 ? 'flex' : 'none' }}
+ onClick={onMenuClick}
+ >
+ Еще
+
+
+
+ >
+ );
+};
diff --git a/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.types.ts b/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.types.ts
new file mode 100644
index 000000000..536f0be1b
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderNavigation/HeaderNavigation.types.ts
@@ -0,0 +1,15 @@
+import { ReactNode } from 'react';
+
+import { HeaderNavigationClasses } from './HeaderNavigation.classes';
+
+import { SxProps, Theme } from '@mui/material';
+
+export interface HeaderNavigationProps {
+ children?: ReactNode;
+ /** Override or extend the styles applied to the component. */
+ classes?: Partial;
+ /** Class applied to the root element. */
+ className?: string;
+ /** The system prop that allows defining system overrides as well as additional CSS styles. */
+ sx?: SxProps;
+}
diff --git a/packages/react/src/components/Header/HeaderNavigation/index.ts b/packages/react/src/components/Header/HeaderNavigation/index.ts
new file mode 100644
index 000000000..c74657abb
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderNavigation/index.ts
@@ -0,0 +1,3 @@
+export { HeaderNavigation } from './HeaderNavigation';
+export { HeaderNavigationClasses, headerNavigationClasses, HeaderNavigationClassKey } from './HeaderNavigation.classes';
+export { HeaderNavigationProps } from './HeaderNavigation.types';
diff --git a/packages/react/src/components/Header/HeaderSearch/HeaderSearch.api.mdx b/packages/react/src/components/Header/HeaderSearch/HeaderSearch.api.mdx
new file mode 100644
index 000000000..bc1c35f1d
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderSearch/HeaderSearch.api.mdx
@@ -0,0 +1,37 @@
+import { Meta } from '@storybook/blocks';
+import LinkTo from '@storybook/addon-links/react';
+import { TableInterface } from '~storybook/components/TableInterface';
+
+
+
+# HeaderSearch API
+
+```js
+import { HeaderSearch } from '@esfront/react';
+```
+
+## Component name
+
+The name `ESHeaderSearch` can be used when providing default props in the theme.
+
+## Props
+
+
+
+
+
+## CSS
+
+
+
+
+
+## Demos
+
+
diff --git a/packages/react/src/components/Header/HeaderSearch/HeaderSearch.classes.ts b/packages/react/src/components/Header/HeaderSearch/HeaderSearch.classes.ts
new file mode 100644
index 000000000..0293bca92
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderSearch/HeaderSearch.classes.ts
@@ -0,0 +1,13 @@
+import { generateUtilityClass, generateUtilityClasses } from '@mui/material';
+
+export type HeaderSearchClasses = {
+ /** Styles applied to the root element. */
+ root: string;
+};
+export type HeaderSearchClassKey = keyof HeaderSearchClasses;
+
+export function getHeaderSearchUtilityClass(slot: string): string {
+ return generateUtilityClass('ESHeaderSearch', slot);
+}
+
+export const headerSearchClasses: HeaderSearchClasses = generateUtilityClasses('ESHeaderSearch', ['root']);
diff --git a/packages/react/src/components/Header/HeaderSearch/HeaderSearch.tsx b/packages/react/src/components/Header/HeaderSearch/HeaderSearch.tsx
new file mode 100644
index 000000000..087e78ac0
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderSearch/HeaderSearch.tsx
@@ -0,0 +1,144 @@
+import { HeaderSearchProps } from './HeaderSearch.types';
+
+import clsx from 'clsx';
+import { getHeaderSearchUtilityClass } from './HeaderSearch.classes';
+
+import { unstable_composeClasses as composeClasses } from '@mui/base';
+
+import { styled, useThemeProps } from '@mui/material/styles';
+import { inputAdornmentClasses } from '@mui/material/InputAdornment';
+import { inputBaseClasses } from '@mui/material/InputBase';
+import { outlinedInputClasses } from '@mui/material/OutlinedInput';
+import TextField, { textFieldClasses } from '@mui/material/TextField';
+
+import { buttonClasses } from '../../Button';
+import { svgIconClasses } from '../../SvgIcon';
+
+type HeaderSearchOwnerState = {
+ classes?: HeaderSearchProps['classes'];
+ variantProp: NonNullable;
+};
+
+const useUtilityClasses = (ownerState: HeaderSearchOwnerState) => {
+ const { classes, variantProp } = ownerState;
+
+ const slots = {
+ root: ['root', variantProp],
+ };
+
+ return composeClasses(slots, getHeaderSearchUtilityClass, classes);
+};
+
+const HeaderSearchRoot = styled(TextField, {
+ name: 'ESHeaderSearch',
+ slot: 'Root',
+ overridesResolver: (props, styles) => styles.root,
+})<{ ownerState: HeaderSearchOwnerState }>(({ theme }) => ({
+ flexGrow: 1,
+
+ variants: [
+ {
+ props: {
+ variantProp: 'borderless',
+ },
+ style: {
+ [`& .${outlinedInputClasses.root}`]: {
+ [`&:has(.${inputAdornmentClasses.positionStart} > .${svgIconClasses.root})`]: {
+ paddingLeft: '8px',
+ },
+ [`&:has(.${inputAdornmentClasses.positionEnd} .${buttonClasses.variantText}:last-child)`]: {
+ paddingRight: '4px',
+ },
+ },
+
+ [`& .${outlinedInputClasses.notchedOutline}`]: {
+ display: 'none',
+ },
+
+ [`& .${inputAdornmentClasses.positionStart}`]: {
+ [`& > .${svgIconClasses.root}`]: {
+ color: theme.vars.palette.monoA.A900,
+ },
+ },
+
+ [`& .${inputAdornmentClasses.positionEnd}`]: {
+ [`& .${buttonClasses.variantText}`]: {
+ '--icon': theme.vars.palette.monoA.A500,
+ },
+ },
+ },
+ },
+ {
+ props: {
+ variantProp: 'outlined',
+ },
+ style: {
+ [`& .${outlinedInputClasses.root}`]: {
+ [`&:has(.${inputAdornmentClasses.positionStart} > .${svgIconClasses.root})`]: {
+ paddingLeft: '8px',
+ },
+ [`&:has(.${inputAdornmentClasses.positionStart} .${buttonClasses.variantContained})`]: {
+ paddingLeft: '4px',
+ },
+ [`&:has(.${inputAdornmentClasses.positionEnd} .${buttonClasses.variantContained}:last-child)`]: {
+ paddingRight: 0,
+ },
+ [`&:has(.${inputAdornmentClasses.positionEnd} .${buttonClasses.variantText}:last-child)`]: {
+ paddingRight: '4px',
+ },
+ },
+
+ [`& .${inputAdornmentClasses.positionStart}`]: {
+ [`& > .${svgIconClasses.root}`]: {
+ color: theme.vars.palette.monoA.A500,
+ },
+ },
+
+ [`& .${inputAdornmentClasses.positionEnd}`]: {
+ [`& .${buttonClasses.variantContained}`]: {
+ borderBottomLeftRadius: 0,
+ borderTopLeftRadius: 0,
+ zIndex: 1,
+ },
+
+ [`& .${buttonClasses.variantText}`]: {
+ '--icon': theme.vars.palette.monoA.A500,
+ },
+
+ [`& .${buttonClasses.variantText}.${buttonClasses.size100}`]: {
+ '--icon': theme.vars.palette.monoA.A400,
+ marginRight: '8px',
+ },
+ },
+ },
+ },
+ ],
+}));
+
+export const HeaderSearch = (inProps: HeaderSearchProps) => {
+ const {
+ classes: inClasses,
+ className,
+ variant: variantProp = 'outlined',
+
+ ...props
+ } = useThemeProps({
+ props: inProps,
+ name: 'ESHeaderSearch',
+ });
+
+ const ownerState = { classes: inClasses, variantProp };
+ const classes = useUtilityClasses(ownerState);
+
+ return (
+
+ );
+};
diff --git a/packages/react/src/components/Header/HeaderSearch/HeaderSearch.types.ts b/packages/react/src/components/Header/HeaderSearch/HeaderSearch.types.ts
new file mode 100644
index 000000000..fcab67410
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderSearch/HeaderSearch.types.ts
@@ -0,0 +1,9 @@
+import { TextFieldProps } from '@mui/material';
+
+export type HeaderSearchProps = {
+ /**
+ * The variant of the component.
+ * @default 'outlined'
+ */
+ variant?: 'borderless' | 'outlined';
+} & Omit;
diff --git a/packages/react/src/components/Header/HeaderSearch/index.ts b/packages/react/src/components/Header/HeaderSearch/index.ts
new file mode 100644
index 000000000..8a0d55d16
--- /dev/null
+++ b/packages/react/src/components/Header/HeaderSearch/index.ts
@@ -0,0 +1,3 @@
+export { HeaderSearch } from './HeaderSearch';
+export { HeaderSearchClasses, headerSearchClasses, HeaderSearchClassKey } from './HeaderSearch.classes';
+export { HeaderSearchProps } from './HeaderSearch.types';
diff --git a/packages/react/src/components/Header/index.ts b/packages/react/src/components/Header/index.ts
new file mode 100644
index 000000000..1fe89bf3c
--- /dev/null
+++ b/packages/react/src/components/Header/index.ts
@@ -0,0 +1,8 @@
+export { Header } from './Header';
+export { HeaderClasses, headerClasses, HeaderClassKey } from './Header.classes';
+export { HeaderProps } from './Header.types';
+export * from './HeaderActions';
+export * from './HeaderLine';
+export * from './HeaderLogo';
+export * from './HeaderNavigation';
+export * from './HeaderSearch';
diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts
index 206915895..45166e221 100644
--- a/packages/react/src/components/index.ts
+++ b/packages/react/src/components/index.ts
@@ -32,6 +32,7 @@ export * from './FormatDate';
export * from './FormatSize';
export * from './FormControlLabel';
export * from './Gallery';
+export * from './Header';
export * from './InformationIcon';
export * from './Kbd';
export * from './LinearProgress';
diff --git a/packages/react/src/icons/IconElonsoft.tsx b/packages/react/src/icons/IconElonsoft.tsx
index 0b246d5c1..e2f08adf0 100644
--- a/packages/react/src/icons/IconElonsoft.tsx
+++ b/packages/react/src/icons/IconElonsoft.tsx
@@ -2,7 +2,7 @@ import { SvgIcon, SvgIconProps } from '../components/SvgIcon';
export const IconElonsoft = (props: SvgIconProps) => {
return (
-
+