Skip to content

Commit

Permalink
Merge pull request #377 from qoretechnologies/feature/resizable-menu
Browse files Browse the repository at this point in the history
Update package version and add resizable property to ReqoreMenu
  • Loading branch information
Foxhoundn authored Apr 19, 2024
2 parents 2c42069 + 119f294 commit eacba71
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 17 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@qoretechnologies/reqore",
"version": "0.40.12",
"version": "0.41.0",
"description": "ReQore is a highly theme-able and modular UI library for React",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
57 changes: 41 additions & 16 deletions src/components/Menu/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Resizable, ResizableProps } from 're-resizable';
import React, { forwardRef } from 'react';
import styled, { css } from 'styled-components';
import { HALF_PADDING_FROM_SIZE, RADIUS_FROM_SIZE } from '../../constants/sizes';
import { IReqoreCustomTheme, IReqoreTheme, TReqoreIntent } from '../../constants/theme';
import ReqoreThemeProvider from '../../containers/ThemeProvider';
import { changeDarkness, changeLightness, getMainBackgroundColor } from '../../helpers/colors';
import { useCloneThroughFragments } from '../../hooks/useCloneThroughFragments';
import { useCombinedRefs } from '../../hooks/useCombinedRefs';
import { useReqoreTheme } from '../../hooks/useTheme';
import {
IReqoreComponent,
Expand All @@ -31,6 +33,10 @@ export interface IReqoreMenuProps
rounded?: boolean;
padded?: boolean;
itemGap?: IReqoreControlGroupProps['gapSize'];
resizable?: Omit<ResizableProps, 'enable'> & {
enable?: Pick<ResizableProps['enable'], 'left' | 'right'>;
};
showResizableBorder?: boolean;
}

export interface IReqoreMenuStyle extends IReqoreMenuProps {
Expand All @@ -40,27 +46,32 @@ export interface IReqoreMenuStyle extends IReqoreMenuProps {
const StyledReqoreMenu = styled.div<IReqoreMenuStyle>`
width: ${({ width }) => width || undefined};
min-width: ${({ width }) => (width ? undefined : '160px')};
padding: ${({ padded = true, size }) =>
padded ? `${HALF_PADDING_FROM_SIZE[size]}px` : undefined};
padding: ${({ padded = true, _size }) =>
padded ? `${HALF_PADDING_FROM_SIZE[_size]}px` : undefined};
max-height: ${({ maxHeight }) => maxHeight || undefined};
overflow-y: auto;
overflow-x: hidden;
background-color: ${({ theme, transparent }) =>
transparent ? 'transparent' : changeDarkness(getMainBackgroundColor(theme), 0.03)};
border-radius: ${({ rounded, size }) => (rounded ? `${RADIUS_FROM_SIZE[size]}px` : `0`)};
border-radius: ${({ rounded, _size }) => (rounded ? `${RADIUS_FROM_SIZE[_size]}px` : `0`)};
${({ theme, position, size, padded }) =>
position
${({ theme, position, _size, padded, isResizableLeft, showResizableBorder }) =>
position === 'right' || (isResizableLeft && showResizableBorder)
? css`
border-${position === 'left' ? 'right' : 'left'}: 1px solid ${changeLightness(
theme.main,
0.05
)};
padding-${position === 'left' ? 'right' : 'left'}: ${
!padded ? `${HALF_PADDING_FROM_SIZE[size]}px` : undefined
};
`
border-left: 1px ${isResizableLeft && showResizableBorder ? 'dashed' : 'solid'}
${changeLightness(theme.main, 0.05)};
padding-left: ${!padded ? `${HALF_PADDING_FROM_SIZE[_size]}px` : undefined};
`
: undefined}
${({ theme, position, _size, padded, isResizableRight, showResizableBorder }) =>
position === 'left' || (isResizableRight && showResizableBorder)
? css`
border-right: 1px ${isResizableRight && showResizableBorder ? 'dashed' : 'solid'}
${changeLightness(theme.main, 0.05)};
padding-right: ${!padded ? `${HALF_PADDING_FROM_SIZE[_size]}px` : undefined};
`
: undefined}
`;

Expand All @@ -78,11 +89,13 @@ const ReqoreMenu = forwardRef<HTMLDivElement, IReqoreMenuProps>(
minimal,
size = 'normal',
itemGap,
resizable,
...rest
}: IReqoreMenuProps,
ref
) => {
const theme = useReqoreTheme('main', customTheme, intent);
const { targetRef } = useCombinedRefs(ref);
const { clone } = useCloneThroughFragments((props) => ({
_insidePopover: props?._insidePopover ?? _insidePopover,
_popoverId: props?._popoverId ?? _popoverId,
Expand All @@ -97,12 +110,24 @@ const ReqoreMenu = forwardRef<HTMLDivElement, IReqoreMenuProps>(
<ReqoreThemeProvider theme={theme}>
<StyledReqoreMenu
{...rest}
{...resizable}
as={!!resizable ? Resizable : 'div'}
isResizableRight={resizable?.enable?.right}
isResizableLeft={resizable?.enable?.left}
flat={flat}
position={position}
size={size}
ref={ref}
theme={theme}
_size={size}
className={`${rest.className || ''} reqore-menu`}
theme={theme}
ref={(curRef) => {
let _ref = curRef;

if (curRef?.resizable) {
_ref = curRef.resizable;
}

targetRef.current = _ref;
}}
>
<ReqoreControlGroup vertical gapSize={itemGap} fluid>
{clone(children)}
Expand Down
29 changes: 29 additions & 0 deletions src/stories/Menu/Menu.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,32 @@ export const SubmenuCanBeToggled: Story = {
await fireEvent.click(canvas.queryAllByText('Collapsed submenu')[0]);
},
};

export const Resizable: Story = {
render: Template,

args: {
position: 'left',
showResizableBorder: true,
resizable: {
enable: { left: true },
minWidth: 400,
maxWidth: 600,
defaultSize: { width: 400, height: '100%' },
},
},
};

export const ResizableBothSidesWithBorder: Story = {
render: Template,

args: {
showResizableBorder: true,
resizable: {
enable: { right: true, left: true },
minWidth: 400,
maxWidth: 600,
defaultSize: { width: 400, height: '100%' },
},
},
};

0 comments on commit eacba71

Please sign in to comment.