diff --git a/packages/react/src/components/BoxDrawing/BoxDrawing.classes.ts b/packages/react/src/components/BoxDrawing/BoxDrawing.classes.ts new file mode 100644 index 000000000..04ff4ec9f --- /dev/null +++ b/packages/react/src/components/BoxDrawing/BoxDrawing.classes.ts @@ -0,0 +1,13 @@ +import { generateUtilityClass, generateUtilityClasses } from '@mui/material'; + +export type BoxDrawingClasses = { + /** Styles applied to the root element. */ + root: string; +}; +export type BoxDrawingClassKey = keyof BoxDrawingClasses; + +export function getBoxDrawingUtilityClass(slot: string): string { + return generateUtilityClass('ESBoxDrawing', slot); +} + +export const boxDrawingClasses: BoxDrawingClasses = generateUtilityClasses('ESBoxDrawing', ['root']); diff --git a/packages/react/src/components/BoxDrawing/BoxDrawing.tsx b/packages/react/src/components/BoxDrawing/BoxDrawing.tsx new file mode 100644 index 000000000..05b0283c9 --- /dev/null +++ b/packages/react/src/components/BoxDrawing/BoxDrawing.tsx @@ -0,0 +1,64 @@ +import { BoxDrawingProps } from './BoxDrawing.types'; + +import clsx from 'clsx'; +import { getBoxDrawingUtilityClass } from './BoxDrawing.classes'; + +import { unstable_composeClasses as composeClasses } from '@mui/base'; + +import { useThemeProps } from '@mui/material/styles'; +import { styled } from '@mui/material'; + +type BoxDrawingOwnerState = { + classes?: BoxDrawingProps['classes']; + bottomOffset?: BoxDrawingProps['bottomOffset']; +}; + +const useUtilityClasses = (ownerState: BoxDrawingOwnerState) => { + const { classes } = ownerState; + + const slots = { + root: ['root'], + container: ['container'] + }; + + return composeClasses(slots, getBoxDrawingUtilityClass, classes); +}; + +const BoxDrawingRoot = styled('div', { + name: 'ESBoxDrawing', + slot: 'Root', + overridesResolver: (props, styles) => { + return [styles.root]; + } +})<{ ownerState: BoxDrawingOwnerState }>(({ ownerState: { bottomOffset }, theme }) => ({ + position: 'absolute', + borderLeft: `1px dashed ${theme.vars.palette.monoA.A400}`, + borderBottom: `1px dashed ${theme.vars.palette.monoA.A400}`, + borderRadius: '0px 0px 0px 4px', + width: '7px', + height: `calc(100% - ${bottomOffset ?? '0'}px)`, + backgroundColor: 'transparent', + left: '20px', + top: 0 +})); + +export const BoxDrawing = (inProps: BoxDrawingProps) => { + const { + className, + classes: inClasses, + bottomOffset, + ...props + } = useThemeProps({ + props: inProps, + name: 'ESBoxDrawing' + }); + + const ownerState = { + classes: inClasses, + bottomOffset + }; + + const classes = useUtilityClasses(ownerState); + + return ; +}; diff --git a/packages/react/src/components/BoxDrawing/BoxDrawing.types.ts b/packages/react/src/components/BoxDrawing/BoxDrawing.types.ts new file mode 100644 index 000000000..99ee72e4a --- /dev/null +++ b/packages/react/src/components/BoxDrawing/BoxDrawing.types.ts @@ -0,0 +1,16 @@ +/* eslint-disable @typescript-eslint/ban-types */ + +import { BoxDrawingClasses } from './BoxDrawing.classes'; + +import { SxProps, Theme } from '@mui/material'; + +export interface BoxDrawingProps { + /** Override or extend the styles applied to the component. */ + classes?: Partial; + /** The system prop that allows defining system overrides as well as additional CSS styles. */ + sx?: SxProps; + /** Class applied to the root element. */ + className?: string; + + bottomOffset?: string; +} diff --git a/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.classes.ts b/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.classes.ts new file mode 100644 index 000000000..0b89c1a79 --- /dev/null +++ b/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.classes.ts @@ -0,0 +1,13 @@ +import { generateUtilityClass, generateUtilityClasses } from '@mui/material'; + +export type BoxDrawingItemClasses = { + /** Styles applied to the root element. */ + root: string; +}; +export type BoxDrawingItemClassKey = keyof BoxDrawingItemClasses; + +export function getBoxDrawingItemUtilityClass(slot: string): string { + return generateUtilityClass('ESBoxDrawingItem', slot); +} + +export const boxDrawingItemClasses: BoxDrawingItemClasses = generateUtilityClasses('ESBoxDrawingItem', ['root']); diff --git a/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.tsx b/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.tsx new file mode 100644 index 000000000..e06a9e8f8 --- /dev/null +++ b/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.tsx @@ -0,0 +1,83 @@ +import { BoxDrawingItemProps } from './BoxDrawingItem.types'; + +import clsx from 'clsx'; +import { getBoxDrawingItemUtilityClass } from './BoxDrawingItem.classes'; + +import { unstable_composeClasses as composeClasses } from '@mui/base'; + +import { useThemeProps } from '@mui/material/styles'; +import { styled } from '@mui/material'; + +type BoxDrawingItemOwnerState = { + classes?: BoxDrawingItemProps['classes']; + isLast?: BoxDrawingItemProps['isLast']; +}; + +const useUtilityClasses = (ownerState: BoxDrawingItemOwnerState) => { + const { classes } = ownerState; + + const slots = { + root: ['root'] + }; + + return composeClasses(slots, getBoxDrawingItemUtilityClass, classes); +}; + +const BoxDrawingItemRoot = styled('div', { + name: 'ESBoxDrawingItem', + slot: 'Root', + overridesResolver: (props, styles) => { + const { + ownerState: { clickable } + } = props; + + return [styles.root, clickable && styles.clickable]; + } +})<{ ownerState: BoxDrawingItemOwnerState }>(({ ownerState: { isLast }, theme }) => ({ + position: 'absolute', + + top: 'calc(50% - 1.5px)', + left: '27.5px', + width: '3px', + height: '3px', + borderRadius: '50%', + background: theme.vars.palette.monoA.A400, + + '&::after': { + content: '""', + display: 'block', + position: 'absolute', + borderBottom: `1px dashed ${theme.vars.palette.monoA.A400}`, + width: '7px', + backgroundColor: 'transparent', + left: '-7.5px', + top: 'calc(50% - 0.5px)' + }, + + ...(isLast && { + '&::after': { + display: 'none' + } + }) +})); + +export const BoxDrawingItem = (inProps: BoxDrawingItemProps) => { + const { + className, + classes: inClasses, + isLast, + ...props + } = useThemeProps({ + props: inProps, + name: 'ESBoxDrawingItem' + }); + + const ownerState = { + classes: inClasses, + isLast + }; + + const classes = useUtilityClasses(ownerState); + + return ; +}; diff --git a/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.types.ts b/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.types.ts new file mode 100644 index 000000000..6f1c422b9 --- /dev/null +++ b/packages/react/src/components/BoxDrawing/BoxDrawingItem/BoxDrawingItem.types.ts @@ -0,0 +1,16 @@ +/* eslint-disable @typescript-eslint/ban-types */ + +import { BoxDrawingItemClasses } from './BoxDrawingItem.classes'; + +import { SxProps, Theme } from '@mui/material'; + +export interface BoxDrawingItemProps { + /** Override or extend the styles applied to the component. */ + classes?: Partial; + /** The system prop that allows defining system overrides as well as additional CSS styles. */ + sx?: SxProps; + /** Class applied to the root element. */ + className?: string; + + isLast?: boolean; +} diff --git a/packages/react/src/components/BoxDrawing/BoxDrawingItem/index.ts b/packages/react/src/components/BoxDrawing/BoxDrawingItem/index.ts new file mode 100644 index 000000000..a4cb5a3b2 --- /dev/null +++ b/packages/react/src/components/BoxDrawing/BoxDrawingItem/index.ts @@ -0,0 +1,3 @@ +export { BoxDrawingItem } from './BoxDrawingItem'; +export { BoxDrawingItemClasses, boxDrawingItemClasses, BoxDrawingItemClassKey } from './BoxDrawingItem.classes'; +export { BoxDrawingItemProps } from './BoxDrawingItem.types'; diff --git a/packages/react/src/components/BoxDrawing/index.ts b/packages/react/src/components/BoxDrawing/index.ts new file mode 100644 index 000000000..53ba954d3 --- /dev/null +++ b/packages/react/src/components/BoxDrawing/index.ts @@ -0,0 +1,3 @@ +export { BoxDrawing } from './BoxDrawing'; +export { BoxDrawingClasses, boxDrawingClasses, BoxDrawingClassKey } from './BoxDrawing.classes'; +export { BoxDrawingProps } from './BoxDrawing.types'; diff --git a/packages/react/src/components/Sidebar/Sidebar.stories.tsx b/packages/react/src/components/Sidebar/Sidebar.stories.tsx index 74686b259..6b62858ac 100644 --- a/packages/react/src/components/Sidebar/Sidebar.stories.tsx +++ b/packages/react/src/components/Sidebar/Sidebar.stories.tsx @@ -16,6 +16,8 @@ import { SidebarSpacer } from './SidebarSpacer'; import { SidebarToggle } from './SidebarToggle'; import { IconAccountLc, IconAt, IconBellFill, IconMagnify } from '../../icons'; +import { BoxDrawing } from '../BoxDrawing'; +import { BoxDrawingItem } from '../BoxDrawing/BoxDrawingItem'; type Args = ComponentProps & { behaviour?: SidebarMenuProps['behaviour']; exclusive?: boolean }; @@ -138,10 +140,12 @@ export const Demo: Story = { ))} } id="1" text={locale === 'en' ? 'Files' : 'Файлы'}> + {[...Array(8)].map((_, i) => ( } text={(locale === 'en' ? 'File' : 'Файл') + ' №' + i} onClick={() => console.info(`File ${i}`)} /> diff --git a/packages/react/src/components/Sidebar/SidebarItem/SidebarItem.tsx b/packages/react/src/components/Sidebar/SidebarItem/SidebarItem.tsx index 868cbdc5c..7d60c5876 100644 --- a/packages/react/src/components/Sidebar/SidebarItem/SidebarItem.tsx +++ b/packages/react/src/components/Sidebar/SidebarItem/SidebarItem.tsx @@ -224,6 +224,7 @@ const SidebarItemNestedMenu = styled('div', { flexDirection: 'column', gap: '2px', marginTop: '2px', + position: 'relative', [`& .${sidebarItemClasses.root}`]: { margin: '0'