Skip to content

Commit

Permalink
Merge pull request #22 from /issues/18
Browse files Browse the repository at this point in the history
* Use useId hook (when available) to generate ids for panels/groups/resize handles.
* Panel component no longer requires an id prop (falling back to useId if none is provided).
* PanelGroup component sets default style position: relative
  • Loading branch information
bvaughn authored Dec 26, 2022
2 parents 103148b + 05a4d3e commit e9fdb3c
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,97 +11,105 @@ export function VerticalGroup() {
const [showBottomPanel, setShowBottomPanel] = useState(true);

return (
<div
className={styles.VerticalFiller}
style={{ backgroundColor: "var(--color-panel-background-alternate)" }}
>
<PanelGroup autoSaveId={GROUP_ID} direction="vertical">
{showTopPanel && (
<Panel
className={styles.PanelColumn}
defaultSize={0.35}
id="top"
minSize={0.2}
order={1}
>
<div className={styles.VerticalFiller}>
<p className={styles.ParagraphOfText}>
This is a "<em>vertical</em>" <code>PanelGroup</code>.
</p>
<p className={styles.ParagraphOfText}>
<button
className={styles.Button}
onClick={() => setShowTopPanel(false)}
>
Hide panel
</button>
</p>
</div>
<PanelResizeHandle>
<div className={styles.VerticalResizeBar} />
</PanelResizeHandle>
</Panel>
)}
<PanelGroup autoSaveId={GROUP_ID} direction="vertical">
{showTopPanel && (
<Panel
className={styles.PanelColumn}
defaultSize={0.35}
id="middle"
minSize={0.35}
order={2}
id="top"
minSize={0.2}
order={1}
>
<div className={styles.VerticalFiller}>
<div
className={styles.VerticalFiller}
style={{
backgroundColor: "var(--color-panel-background-alternate)",
}}
>
<p className={styles.ParagraphOfText}>
This panel uses the <code>minSize</code> prop to prevent it from
shrinking to less than 35% of the total height.
This is a "<em>vertical</em>" <code>PanelGroup</code>.
</p>

{!showTopPanel && (
<p className={styles.ParagraphOfText}>
<button
className={styles.ButtonTop}
onClick={() => setShowTopPanel(true)}
className={styles.Button}
onClick={() => setShowTopPanel(false)}
>
Show top panel
Hide panel
</button>
)}
</p>
</div>
<PanelResizeHandle>
<div className={styles.VerticalResizeBar} />
</PanelResizeHandle>
</Panel>
)}
<Panel
className={styles.PanelColumn}
defaultSize={0.35}
id="middle"
minSize={0.35}
order={2}
>
<div
className={styles.VerticalFiller}
style={{ backgroundColor: "var(--color-panel-background-alternate)" }}
>
<p className={styles.ParagraphOfText}>
This panel uses the <code>minSize</code> prop to prevent it from
shrinking to less than 35% of the total height.
</p>

{!showTopPanel && (
<button
className={styles.ButtonTop}
onClick={() => setShowTopPanel(true)}
>
Show top panel
</button>
)}

{!showBottomPanel && (
{!showBottomPanel && (
<button
className={styles.ButtonBottom}
onClick={() => setShowBottomPanel(true)}
>
Show bottom panel
</button>
)}
</div>
</Panel>
{showBottomPanel && (
<Panel
className={styles.PanelColumn}
defaultSize={0.65}
id="bottom"
minSize={0.2}
order={3}
>
<PanelResizeHandle>
<div className={styles.VerticalResizeBar} />
</PanelResizeHandle>
<div
className={styles.VerticalFiller}
style={{
backgroundColor: "var(--color-panel-background-alternate)",
}}
>
<p className={styles.ParagraphOfText}>
This group uses a solid resize bar, similar to Chrome devtools or
VS Code.
</p>
<p className={styles.ParagraphOfText}>
<button
className={styles.ButtonBottom}
onClick={() => setShowBottomPanel(true)}
className={styles.Button}
onClick={() => setShowBottomPanel(false)}
>
Show bottom panel
Hide panel
</button>
)}
</p>
</div>
</Panel>
{showBottomPanel && (
<Panel
className={styles.PanelColumn}
defaultSize={0.65}
id="bottom"
minSize={0.2}
order={3}
>
<PanelResizeHandle>
<div className={styles.VerticalResizeBar} />
</PanelResizeHandle>
<div className={styles.VerticalFiller}>
<p className={styles.ParagraphOfText}>
This group uses a solid resize bar, similar to Chrome devtools
or VS Code.
</p>
<p className={styles.ParagraphOfText}>
<button
className={styles.Button}
onClick={() => setShowBottomPanel(false)}
>
Hide panel
</button>
</p>
</div>
</Panel>
)}
</PanelGroup>
</div>
)}
</PanelGroup>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,14 @@
align-items: center;
justify-content: center;
overflow: hidden;
border-radius: 0.5rem;
}
.PanelColumn:first-of-type .VerticalFiller {
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
}
.PanelColumn:last-of-type .VerticalFiller {
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
}

.PanelColumn {
Expand Down Expand Up @@ -101,6 +108,7 @@
width: 100%;
position: relative;
padding: 0.25rem 0;
background-color: var(--color-panel-background-alternate);
}
.VerticalResizeBar::after {
content: " ";
Expand Down
4 changes: 4 additions & 0 deletions packages/react-resizable-panels/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.0.13
* [#18](https://github.com/bvaughn/react-resizable-panels/issues/18): Support server-side rendering (e.g. Next JS) by using `useId` (when available). `Panel` components no longer _require_ a user-provided `id` prop and will also fall back to using `useId` when none is provided.
* `PanelGroup` component now sets `position: relative` style by default, as well as an explicit `height` and `width` style.

## 0.0.12
* Bug fix: [#19](https://github.com/bvaughn/react-resizable-panels/issues/19): Fix initial "jump" that could occur when dragging started.
* Bug fix: [#20](https://github.com/bvaughn/react-resizable-panels/issues/20): Stop resize/drag operation on "contextmenu" event.
Expand Down
11 changes: 6 additions & 5 deletions packages/react-resizable-panels/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ React components for resizable panel groups/layouts
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";

<PanelGroup autoSaveId="example" direction="horizontal">
<Panel defaultSize={0.3} id="left">
<Panel defaultSize={0.3}>
<SourcesExplorer />
</Panel>
<Panel defaultSize={0.5} id="middle">
<Panel defaultSize={0.5}>
<PanelResizeHandle />
<SourceViewer />
<PanelResizeHandle />
</Panel>
<Panel defaultSize={0.2} id="right">
<Panel defaultSize={0.2}>
<Console />
</Panel>
</PanelGroup>
Expand All @@ -29,6 +29,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
| `className` | `?string` | Class name
| `direction` | `"horizontal" \| "vertical"` | Group orientation
| `height` | `number` | Height of group (in pixels)
| `id` | `?string` | Optional group id; falls back to `useId` when not provided
| `width` | `number` | Width of group (in pixels)

### `Panel`
Expand All @@ -37,7 +38,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
| `children` | `ReactNode` | Arbitrary React element(s)
| `className` | `?string` | Class name
| `defaultSize` | `?number` | Initial size of panel (relative to other panels within the group)
| `id` | `string` | Panel id (must be unique within the current group)
| `id` | `?string` | Optional panel id (unique within group); falls back to `useId` when not provided
| `minSize` | `?number` | Minum allowable size of panel (0.0 - 1.0)
| `order` | `?number` | Order of panel within group; required for groups with conditionally rendered panels

Expand All @@ -47,7 +48,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
| `children` | `?ReactNode` | Custom drag UI; can be any arbitrary React element(s)
| `className` | `?string` | Class name
| `disabled` | `?boolean` | Disable drag handle
| `id` | `?string` | Optional resize handle id (must be unique within the current group)
| `id` | `?string` | Optional resize handle id (unique within group); falls back to `useId` when not provided

### `PanelContext`
| prop | type | description
Expand Down
21 changes: 12 additions & 9 deletions packages/react-resizable-panels/src/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ReactNode, useContext, useLayoutEffect } from "react";
import useUniqueId from "./hooks/useUniqueId";

import { PanelGroupContext } from "./PanelContexts";

Expand All @@ -9,14 +10,14 @@ export default function Panel({
children = null,
className = "",
defaultSize = 0.1,
id,
id: idFromProps = null,
minSize = 0.1,
order = null,
}: {
children?: ReactNode;
className?: string;
defaultSize?: number;
id: string;
id?: string | null;
minSize?: number;
order?: number | null;
}) {
Expand All @@ -27,6 +28,8 @@ export default function Panel({
);
}

const panelId = useUniqueId(idFromProps);

if (minSize > defaultSize) {
console.error(
`Panel minSize ${minSize} cannot be greater than defaultSize ${defaultSize}`
Expand All @@ -40,25 +43,25 @@ export default function Panel({
useLayoutEffect(() => {
const panel = {
defaultSize,
id,
id: panelId,
minSize,
order,
};

registerPanel(id, panel);
registerPanel(panelId, panel);

return () => {
unregisterPanel(id);
unregisterPanel(panelId);
};
}, [defaultSize, id, minSize, order, registerPanel, unregisterPanel]);
}, [defaultSize, panelId, minSize, order, registerPanel, unregisterPanel]);

const style = getPanelStyle(id);
const style = getPanelStyle(panelId);

return (
<div
className={className}
data-panel-id={id}
id={`data-panel-id-${id}`}
data-panel-id={panelId}
id={`data-panel-id-${panelId}`}
style={style}
>
{children}
Expand Down
14 changes: 11 additions & 3 deletions packages/react-resizable-panels/src/PanelGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
useRef,
useState,
} from "react";
import useUniqueId from "./hooks/useUniqueId";

import { PanelContext, PanelGroupContext } from "./PanelContexts";
import { Direction, PanelData, ResizeEvent } from "./types";
Expand All @@ -22,6 +21,7 @@ import {
panelsMapToSortedArray,
} from "./utils/group";
import { useWindowSplitterPanelGroupBehavior } from "./hooks/useWindowSplitterBehavior";
import useUniqueId from "./hooks/useUniqueId";

export type CommittedValues = {
direction: Direction;
Expand All @@ -39,6 +39,7 @@ type Props = {
className?: string;
direction: Direction;
height: number;
id?: string | null;
width: number;
};

Expand All @@ -52,9 +53,10 @@ export default function PanelGroup({
className = "",
direction,
height,
id: idFromProps = null,
width,
}: Props) {
const groupId = useUniqueId();
const groupId = useUniqueId(idFromProps);

const [activeHandleId, setActiveHandleId] = useState<string | null>(null);
const [panels, setPanels] = useState<PanelDataMap>(new Map());
Expand Down Expand Up @@ -276,7 +278,13 @@ export default function PanelGroup({
return (
<PanelContext.Provider value={panelContext}>
<PanelGroupContext.Provider value={panelGroupContext}>
<div className={className}>{children}</div>
<div
className={className}
data-panel-group-id={groupId}
style={{ height, position: "relative", width }}
>
{children}
</div>
</PanelGroupContext.Provider>
</PanelContext.Provider>
);
Expand Down
Loading

1 comment on commit e9fdb3c

@vercel
Copy link

@vercel vercel bot commented on e9fdb3c Dec 26, 2022

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.