Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add :order prop to Panel #9

Merged
merged 1 commit into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions packages/react-resizable-panels-website/root.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@ code {
border-radius: 0.25em;
}

hr {
width: 100%;
height: 1px;
border: none;
background-color: #454950;
}

h2 {
font-weight: normal;
margin: 0.5rem 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default function HorizontalGroup({
reset vertical sizes
<div className={styles.VerticalDot} />
</button>
<hr />
<span className={styles.HorizontalDivider} />
<button
className={styles.Button}
onClick={() => clearSavedSizes(GROUP_ID, GROUP_ID_VERTICAL)}
Expand Down
141 changes: 85 additions & 56 deletions packages/react-resizable-panels-website/src/VerticalGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,101 @@ import styles from "./styles.module.css";
export const GROUP_ID = "vertical";

export function VerticalGroup() {
const [isPanelHidden, setIsPanelHidden] = useState(false);

const hidePanel = () => setIsPanelHidden(true);
const showPanel = () => setIsPanelHidden(false);
const [showTopPanel, setShowTopPanel] = useState(true);
const [showBottomPanel, setShowBottomPanel] = useState(true);

return (
<PanelGroup autoSaveId={GROUP_ID} direction="vertical">
<Panel
className={styles.PanelRow}
defaultSize={0.35}
id="top"
minSize={0.25}
>
<div
className={
isPanelHidden ? styles.VerticalFiller : styles.VerticalFillerTop
}
style={{ backgroundColor: "var(--color-vertical)" }}
>
<p className={styles.ParagraphOfText}>
This is a "<em>vertical</em>" <code>PanelGroup</code>.
</p>
<p className={styles.ParagraphOfText}>
It has a solid resize bar, similar to Chrome devtools or VS Code.
</p>
<p className={styles.ParagraphOfText}>
It uses the <code>minSize</code> prop to prevent it from shrinking
to less than 35% of the total height.
</p>

{isPanelHidden && (
<button
className={styles.ButtonBottom}
onClick={showPanel}
id="blah"
>
Show panel
</button>
)}
</div>
</Panel>
{isPanelHidden || (
<div
className={styles.VerticalFiller}
style={{ backgroundColor: "var(--color-vertical)" }}
>
<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 panelBefore="top" panelAfter="middle">
<div className={styles.VerticalResizeBar} />
</PanelResizeHandle>
</Panel>
)}
<Panel
className={styles.PanelColumn}
defaultSize={0.65}
id="bottom"
defaultSize={0.35}
id="middle"
minSize={0.35}
order={2}
>
<PanelResizeHandle panelBefore="top" panelAfter="bottom">
<div className={styles.VerticalResizeBar} />
</PanelResizeHandle>
<div
className={styles.VerticalFillerBottom}
style={{ backgroundColor: "var(--color-vertical)" }}
>
<div className={styles.VerticalFiller}>
<p className={styles.ParagraphOfText}>
This panel's visibility can be toggled on or off.
This panel uses the <code>minSize</code> prop to prevent it from
shrinking to less than 35% of the total height.
</p>
<p className={styles.ParagraphOfText}>
<button className={styles.Button} onClick={hidePanel}>
Hide panel

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

{!showBottomPanel && (
<button
className={styles.ButtonBottom}
onClick={() => setShowBottomPanel(true)}
>
Show bottom panel
</button>
)}
</div>
</Panel>
)}
</PanelGroup>
{showBottomPanel && (
<Panel
className={styles.PanelColumn}
defaultSize={0.65}
id="bottom"
minSize={0.2}
order={3}
>
<PanelResizeHandle panelBefore="middle" panelAfter="bottom">
<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>
);
}
33 changes: 19 additions & 14 deletions packages/react-resizable-panels-website/src/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@
.HorizontalFiller,
.HorizontalFillerLeft,
.HorizontalFillerRight,
.VerticalFiller,
.VerticalFillerBottom,
.VerticalFillerTop {
.VerticalFiller {
height: 100%;
width: 100%;
background-color: #192230;
display: flex;
flex-direction: column;
align-items: center;
Expand All @@ -31,14 +28,6 @@
.VerticalFiller {
border-radius: 0.5rem;
}
.VerticalFillerTop {
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
}
.VerticalFillerBottom {
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
}

.PanelRow {
display: flex;
Expand All @@ -62,7 +51,8 @@
}

.Button,
.ButtonBottom {
.ButtonBottom,
.ButtonTop {
color: #ffffff;
background: #2a3343;
border: 1px solid #18181a;
Expand All @@ -71,7 +61,8 @@
cursor: pointer;
}
.Button:hover,
.ButtonBottom:hover {
.ButtonBottom:hover,
.ButtonTop:hover {
background: #454950;
}

Expand Down Expand Up @@ -101,3 +92,17 @@
bottom: 1ch;
right: 1ch;
}
.ButtonTop {
position: absolute;
top: 1ch;
right: 1ch;
}

.HorizontalDivider {
display: block;
width: 100%;
height: 1px;
border: none;
background-color: #454950;
margin: 0.5rem 0;
}
3 changes: 3 additions & 0 deletions packages/react-resizable-panels/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.0.4
* [#8](https://github.com/bvaughn/react-resizable-panels/issues/8): Added optional `order` prop to `Panel` to improve conditional rendering.

## 0.0.3
* [#3](https://github.com/bvaughn/react-resizable-panels/issues/3): `Panel`s can be conditionally rendered within a group. `PanelGroup` will persist separate layouts for each combination of visible panels.

Expand Down
1 change: 1 addition & 0 deletions packages/react-resizable-panels/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
| `defaultSize` | `?number` | Initial size of panel (relative to other panels within the group)
| `id` | `string` | Panel id (must be unique within the current group)
| `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

### `PanelResizeHandle`
| prop | type | description
Expand Down
5 changes: 4 additions & 1 deletion packages/react-resizable-panels/src/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ export default function Panel({
defaultSize = 0.1,
id,
minSize = 0.1,
order = null,
}: {
children?: ReactNode;
className?: string;
defaultSize?: number;
id: string;
minSize?: number;
order?: number | null;
}) {
const context = useContext(PanelGroupContext);
if (context === null) {
Expand All @@ -40,14 +42,15 @@ export default function Panel({
defaultSize,
id,
minSize,
order,
};

registerPanel(id, panel);

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

const style = getPanelStyle(id);

Expand Down
15 changes: 10 additions & 5 deletions packages/react-resizable-panels/src/PanelGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export default function PanelGroup({
if (defaultSizes != null) {
setSizes(defaultSizes);
} else {
const panelsArray: PanelData[] = Array.from(panels.values());
const panelsArray = panelsMapToSortedArray(panels);
const totalWeight = panelsArray.reduce((weight, panel) => {
return weight + panel.defaultSize;
}, 0);
Expand Down Expand Up @@ -237,7 +237,7 @@ function adjustByDelta(
return prevSizes;
}

const panelsArray: PanelData[] = Array.from(panels.values());
const panelsArray = panelsMapToSortedArray(panels);

const nextSizes = prevSizes.concat();

Expand Down Expand Up @@ -295,7 +295,8 @@ function createLocalStorageKey(
autoSaveId: string,
panels: Map<string, PanelData>
): string {
const panelIds = Array.from(panels.keys()).sort();
const panelsArray = panelsMapToSortedArray(panels);
const panelIds = panelsArray.map((panel) => panel.id);

return `PanelGroup:sizes:${autoSaveId}${panelIds.join("|")}`;
}
Expand All @@ -308,7 +309,7 @@ function getOffset(
height: number,
width: number
): number {
const panelsArray: PanelData[] = Array.from(panels.values());
const panelsArray = panelsMapToSortedArray(panels);

let index = panelsArray.findIndex((panel) => panel.id === id);
if (index < 0) {
Expand Down Expand Up @@ -339,7 +340,7 @@ function getSize(
return totalSize;
}

const panelsArray: PanelData[] = Array.from(panels.values());
const panelsArray = panelsMapToSortedArray(panels);

const index = panelsArray.findIndex((panel) => panel.id === id);
const size = sizes[index];
Expand All @@ -349,3 +350,7 @@ function getSize(

return Math.round(size * totalSize);
}

function panelsMapToSortedArray(panels: Map<string, PanelData>): PanelData[] {
return Array.from(panels.values()).sort((a, b) => a.order - b.order);
}
1 change: 1 addition & 0 deletions packages/react-resizable-panels/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type PanelData = {
defaultSize: number;
id: string;
minSize: number;
order: number | null;
};

export type ResizeHandler = (event: MouseEvent) => void;