Skip to content

Commit

Permalink
Support pixel-based panel constraints (#176)
Browse files Browse the repository at this point in the history
Relates to issues #46, #47, #51, #78, #114, #128, #141

This PR adds a new prop (`units`) to `PanelGroup`. This prop defaults to
"percentage" but can be set to "pixels" for static, pixel based layout
constraints.

This can be used to add enable pixel-based min/max and default size
values, e.g.:
```tsx
 <PanelGroup direction="horizontal" units="pixels">
   {/* Will be constrained to 100-200 pixels (assuming group is large enough to permit this) */}
   <Panel minSize={100} maxSize={200} />
   <PanelResizeHandle />
   <Panel />
   <PanelResizeHandle />
   <Panel />
 </PanelGroup>
```

Imperative API methods are also able to work with either pixels or
percentages now. They default to whatever units the group has been
configured to use, but can be overridden with an additional, optional
parameter, e.g.
```ts
panelRef.resize(100, "pixels");
panelGroupRef.setLayout([25, 50, 25], "percentages");

// Works for getters too, e.g.
const percentage = panelRef.getSize("percentages");
const pixels = panelRef.getSize("pixels");

const layout = panelGroupRef.getLayout("pixels");
```

See the docs for more:
[.../examples/pixel-based-layouts](https://react-resizable-panels-git-panelgroup-layout-val-2424f0-bvaughn.vercel.app/examples/pixel-based-layouts)
  • Loading branch information
bvaughn authored Aug 13, 2023
1 parent a4b4cd6 commit ed8d712
Show file tree
Hide file tree
Showing 46 changed files with 2,277 additions and 606 deletions.
5 changes: 5 additions & 0 deletions packages/react-resizable-panels-website/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createBrowserRouter, RouterProvider } from "react-router-dom";

import HomeRoute from "./src/routes/Home";
import ConditionalExampleRoute from "./src/routes/examples/Conditional";
import PixelBasedLayoutsRoute from "./src/routes/examples/PixelBasedLayouts";
import ExternalPersistenceExampleRoute from "./src/routes/examples/ExternalPersistence";
import HorizontalExampleRoute from "./src/routes/examples/Horizontal";
import ImperativePanelApiExampleRoute from "./src/routes/examples/ImperativePanelApi";
Expand All @@ -24,6 +25,10 @@ const router = createBrowserRouter([
path: "/examples/conditional",
element: <ConditionalExampleRoute />,
},
{
path: "/examples/pixel-based-layouts",
element: <PixelBasedLayoutsRoute />,
},
{
path: "/examples/external-persistence",
element: <ExternalPersistenceExampleRoute />,
Expand Down
22 changes: 21 additions & 1 deletion packages/react-resizable-panels-website/src/components/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ import styles from "./Icon.module.css";
export type IconType =
| "chevron-down"
| "close"
| "collapse"
| "css"
| "expand"
| "files"
| "horizontal-collapse"
| "horizontal-expand"
| "html"
| "loading"
| "markdown"
| "resize"
| "resize-horizontal"
| "resize-vertical"
| "search"
| "typescript";
| "typescript"
| "warning";

export default function Icon({
className = "",
Expand All @@ -31,10 +35,18 @@ export default function Icon({
path =
"M20 6.91L17.09 4L12 9.09L6.91 4L4 6.91L9.09 12L4 17.09L6.91 20L12 14.91L17.09 20L20 17.09L14.91 12L20 6.91Z";
break;
case "collapse":
path =
"M19.5,3.09L15,7.59V4H13V11H20V9H16.41L20.91,4.5L19.5,3.09M4,13V15H7.59L3.09,19.5L4.5,20.91L9,16.41V20H11V13H4Z";
break;
case "css":
path =
"M5,3L4.35,6.34H17.94L17.5,8.5H3.92L3.26,11.83H16.85L16.09,15.64L10.61,17.45L5.86,15.64L6.19,14H2.85L2.06,18L9.91,21L18.96,18L20.16,11.97L20.4,10.76L21.94,3H5Z";
break;
case "expand":
path =
"M10,21V19H6.41L10.91,14.5L9.5,13.09L5,17.59V14H3V21H10M14.5,10.91L19,6.41V10H21V3H14V5H17.59L13.09,9.5L14.5,10.91Z";
break;
case "files":
path =
"M15,7H20.5L15,1.5V7M8,0H16L22,6V18A2,2 0 0,1 20,20H8C6.89,20 6,19.1 6,18V2A2,2 0 0,1 8,0M4,4V22H20V24H4A2,2 0 0,1 2,22V4H4Z";
Expand All @@ -59,6 +71,10 @@ export default function Icon({
path =
"M20.56 18H3.44C2.65 18 2 17.37 2 16.59V7.41C2 6.63 2.65 6 3.44 6H20.56C21.35 6 22 6.63 22 7.41V16.59C22 17.37 21.35 18 20.56 18M6.81 15.19V11.53L8.73 13.88L10.65 11.53V15.19H12.58V8.81H10.65L8.73 11.16L6.81 8.81H4.89V15.19H6.81M19.69 12H17.77V8.81H15.85V12H13.92L16.81 15.28L19.69 12Z";
break;
case "resize":
path =
"M10.59,12L14.59,8H11V6H18V13H16V9.41L12,13.41V16H20V4H8V12H10.59M22,2V18H12V22H2V12H6V2H22M10,14H4V20H10V14Z";
break;
case "resize-horizontal":
path =
"M18,16V13H15V22H13V2H15V11H18V8L22,12L18,16M2,12L6,16V13H9V22H11V2H9V11H6V8L2,12Z";
Expand All @@ -75,6 +91,10 @@ export default function Icon({
path =
"M3,3H21V21H3V3M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86M13,11.25H8V12.75H9.5V20H11.25V12.75H13V11.25Z";
break;
case "warning":
path =
"M5,3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19V5A2,2 0 0,1 5,3M13,13V7H11V13H13M13,17V15H11V17H13Z";
break;
}

return (
Expand Down
Loading

1 comment on commit ed8d712

@vercel
Copy link

@vercel vercel bot commented on ed8d712 Aug 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.