diff --git a/package-lock.json b/package-lock.json index 94fd1134..c0f40e57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", "lodash": "^4.17.21", + "re-resizable": "6.10.3", "react-sortablejs": "^6.1.4", "react-syntax-highlighter": "^15.5.0", "react-virtualized-auto-sizer": "^1.0.20", @@ -15288,6 +15289,15 @@ "node": ">= 0.8" } }, + "node_modules/re-resizable": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.10.3.tgz", + "integrity": "sha512-zvWb7X3RJMA4cuSrqoxgs3KR+D+pEXnGrD2FAD6BMYAULnZsSF4b7AOVyG6pC3VVNVOtlagGDCDmZSwWLjjBBw==", + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", diff --git a/package.json b/package.json index f12cc261..32ec3313 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", "lodash": "^4.17.21", + "re-resizable": "6.10.3", "react-sortablejs": "^6.1.4", "react-syntax-highlighter": "^15.5.0", "react-virtualized-auto-sizer": "^1.0.20", diff --git a/src/App.tsx b/src/App.tsx index ab147143..e5017044 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -732,6 +732,23 @@ const App = () => { 7. grow="0" + + + Parent Container: + + border="default" fillWidth=true padding="md" + + + + + + 7. grow="0" + + diff --git a/src/components/Container/Container.tsx b/src/components/Container/Container.tsx index bbd84095..b8bf6c40 100644 --- a/src/components/Container/Container.tsx +++ b/src/components/Container/Container.tsx @@ -9,6 +9,7 @@ import { import { Orientation } from "@/components"; type AlignItemsOptions = "start" | "center" | "end" | "stretch"; +type BorderColor = "default" | "intense" | "muted"; export type GapOptions = "none" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl"; type GrowShrinkOptions = "0" | "1" | "2" | "3" | "4" | "5" | "6"; type JustifyContentOptions = @@ -25,6 +26,7 @@ type WrapOptions = "nowrap" | "wrap" | "wrap-reverse"; export interface ContainerProps { component?: T; + border?: BorderColor; alignItems?: AlignItemsOptions; children?: React.ReactNode; fillWidth?: boolean; @@ -51,6 +53,7 @@ type ContainerPolymorphicComponent = ( const _Container = ( { component, + border, alignItems, children, fillWidth = true, @@ -77,6 +80,7 @@ const _Container = ( ref={ref} as={component ?? "div"} $alignItems={alignItems ?? (orientation === "vertical" ? "start" : "center")} + $border={border} $fillWidth={fillWidth} $gapSize={gap} $grow={grow} @@ -101,6 +105,7 @@ const _Container = ( }; const Wrapper = styled.div<{ $alignItems: AlignItemsOptions; + $border?: BorderColor; $fillWidth?: boolean; $gapSize: GapOptions; $grow?: GrowShrinkOptions; @@ -130,6 +135,8 @@ const Wrapper = styled.div<{ ${({ $overflow }) => ` ${$overflow && `overflow: ${$overflow}`}; `} + ${({ $border, theme }) => + $border ? `border: 1px solid ${theme.click.global.color.stroke[$border]};` : ""} flex-wrap: ${({ $wrap = "nowrap" }) => $wrap}; gap: ${({ theme, $gapSize }) => theme.click.container.gap[$gapSize]}; max-width: ${({ $maxWidth }) => $maxWidth ?? "none"}; diff --git a/src/components/Flyout/Flyout.tsx b/src/components/Flyout/Flyout.tsx index 8890f5c7..168889c0 100644 --- a/src/components/Flyout/Flyout.tsx +++ b/src/components/Flyout/Flyout.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from "react"; +import { ReactNode, useEffect, useState } from "react"; import { Dialog, DialogClose, @@ -25,6 +25,7 @@ import { import { styled } from "styled-components"; import { CrossButton } from "../commonElement"; import { keyframes } from "styled-components"; +import { Resizable } from "re-resizable"; export type FlyoutProps = DialogProps; @@ -62,7 +63,9 @@ export interface DialogContentProps extends RadixDialogContentProps { type?: FlyoutType; strategy?: Strategy; closeOnInteractOutside?: boolean; - width?: string; + resizable?: boolean; + onFlyoutResize?: (width: number) => void; + width?: string | number; align?: DialogContentAlignmentType; } @@ -76,7 +79,7 @@ const FlyoutContent = styled(DialogContent)<{ $size?: FlyoutSizeType; $type?: FlyoutType; $strategy: Strategy; - $width?: string; + $width?: string | number; $align: DialogContentAlignmentType; }>` display: flex; @@ -85,9 +88,9 @@ const FlyoutContent = styled(DialogContent)<{ overflow: hidden; top: 0; bottom: 0; - width: fit-content; - --flyout-width: ${({ theme, $size = "default", $width }) => - $width || theme.click.flyout.size[$size].width}; + width: 100%; + --flyout-width: ${({ $width }) => + (typeof $width === "number" ? `${$width}px` : $width) || "100%"}; animation: ${animationWidth} 500ms cubic-bezier(0.16, 1, 0.3, 1) forwards; ${({ theme, $strategy, $type = "default", $align }) => ` ${$align === "start" ? "left" : "right"}: 0; @@ -138,19 +141,52 @@ const FlyoutContainer = styled.div` gap: inherit; `; +const defaultWidths = { + default: 440, + wide: 600, + narrow: 336, +}; + +const MIN_WIDTH = 200; + const Content = ({ showOverlay = false, children, container, strategy = "relative", - size, + size = "default", type = "default", closeOnInteractOutside = false, - width, + onFlyoutResize, + resizable = false, + width: widthProp, align = "end", onInteractOutside, ...props }: DialogContentProps) => { + const [width, setWidth] = useState(defaultWidths[size]); + + useEffect(() => { + if (typeof widthProp === "number") { + setWidth(Number(widthProp)); + } + }, [widthProp]); + + const resizeEnable = { + top: false, + right: false, + bottom: false, + left: false, + topRight: false, + bottomRight: false, + bottomLeft: false, + topLeft: false, + }; + + if (resizable) { + resizeEnable[align === "start" ? "right" : "left"] = true; + } + return ( {showOverlay && } @@ -166,11 +202,32 @@ const Content = ({ onInteractOutside(e); } }} - $width={width} + $width={resizable ? undefined : widthProp} $align={align} {...props} > - {children} + { + setWidth(currentWidth => currentWidth + delta.width); + if (typeof onFlyoutResize === "function") { + onFlyoutResize(width + delta.width); + } + }} + minWidth={MIN_WIDTH} + enable={resizeEnable} + > + + {children} + + );