Skip to content
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ yarn-error.log*

coverage

storybook-static
storybook-static

# Ignore vs folder
.vs
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Possibility to render the whole PanelSidebarLayout hiding completely the SidebarNav.
- Export for `PanelSidebarNavbar` component. It can be used to render only the Navbar without need of context.

## [5.1.0] - 2025-06-11

### Changed
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"copy-sass": "shx cp -r styles dist/scss",
"lint": "eslint --cache",
"prepack": "yarn build",
"prepare-pr": "yarn prettier . --write && yarn lint && yarn build && yarn test\"",
"prepare-pr": "yarn prettier . --write && yarn lint && yarn build",
"prettier-check": "prettier --check .",
"start": "rollup -c -w",
"start-all": "concurrently \"yarn start\" \"yarn start-yalc\"",
Expand All @@ -62,8 +62,6 @@
"@types/node": "^18.16.3",
"@types/react": "^18.2.5",
"@types/react-dom": "^18.2.3",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"bootstrap": "^5.2.3",
"concurrently": "^8.0.1",
"cross-env": "^7.0.3",
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from "./lib/Layout/AuthenticationLayout";
export * from "./lib/Paging/Paging";

// Panel sidebar layout
export { PanelSidebarNavbar, PanelSidebarNavbarProps } from "./lib/Layout/PanelSideBarLayout/PanelSideBarNavbar";
export * from "./lib/Layout/PanelSideBarLayout/PanelSideBarLayout";
export * from "./lib/Layout/PanelSideBarLayout/PanelSideBar/Context/PanelSideBarContext";
export * from "./lib/Layout/PanelSideBarLayout/PanelSideBar/Definitions/PanelItem";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,24 @@ import { PanelItem } from "../Definitions/PanelItem";
import { PanelLinkRenderer } from "../Definitions/PanelLinkRenderer";
import { MenuItemToggleFn } from "./PanelSideBarContext";

export interface PanelSideBarContextProps<TPanelItemId extends string, TPanelItem> {
export interface SidebarProps {
/**
* If the sidebar is currently open or not
*/
isSidebarOpen: boolean;

/**
* Function for toggling sidebar
*/
toggleSidebar: () => void;

/**
* The theme
*/
theme?: "light" | "dark" | "blue";
}

export interface PanelSideBarContextProps<TPanelItemId extends string, TPanelItem> extends SidebarProps {
/**
* The active panel id.
*/
Expand Down Expand Up @@ -37,20 +54,6 @@ export interface PanelSideBarContextProps<TPanelItemId extends string, TPanelIte
*/
untoggleMenuItems: () => void;

/**
* If the sidebar is currently open or not
*/
isSidebarOpen: boolean;
/**
* Function for toggling sidebar
*/
toggleSidebar: () => void;

/**
* The theme
*/
theme?: "light" | "dark" | "blue";

/**
* Boolean indicating if you want to render first items level as icons or directly as menu entries
*/
Expand Down
38 changes: 29 additions & 9 deletions src/lib/Layout/PanelSideBarLayout/PanelSideBarLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "../../../../styles/Layout/index.scss";
import { PanelSideBar } from "./PanelSideBar/PanelSidebar";
import { PanelSideBarLayoutContent } from "./PanelSideBarLayoutContent";
import { PanelSideBarToggle } from "./PanelSideBar/PanelSideBarToggle";
import { PanelSidebarNavbar } from "./PanelSideBarNavbar";
import { PanelSidebarNavbarInternal, PanelSidebarNavbarInternalProps } from "./PanelSideBarNavbar";
import { usePanelSideBarContext } from "./PanelSideBar/Context/PanelSideBarContext";

export interface PanelSideBarLayoutProps extends PropsWithChildren {
Expand Down Expand Up @@ -38,8 +38,19 @@ export interface PanelSideBarLayoutProps extends PropsWithChildren {
* If use the responsive layout when the screen is sm in order to remove the sidebar overlay.
*/
useResponsiveLayout?: boolean;

/**
* If true, exclude the sidebar menu.
*/
excludeSibebarMenu?: boolean;
}

const PanelSidebarNavbar = (props: Omit<PanelSidebarNavbarInternalProps, "toggleSidebar" | "theme">) => {
const { toggleSidebar, theme } = usePanelSideBarContext();

return <PanelSidebarNavbarInternal toggleSidebar={toggleSidebar} theme={theme} {...props} />;
};

export const PanelSideBarLayout = <TPanelItemId extends string, TPanelItem>(props: PanelSideBarLayoutProps) => {
const {
brand,
Expand All @@ -50,6 +61,7 @@ export const PanelSideBarLayout = <TPanelItemId extends string, TPanelItem>(prop
collapsible = true,
useToggleButton = false,
useResponsiveLayout = false,
excludeSibebarMenu = false,
} = props;

const { isSidebarOpen, toggleSidebar, renderFirstItemsLevelAsTiles, menuItems, activePanelId } = usePanelSideBarContext<
Expand Down Expand Up @@ -83,15 +95,23 @@ export const PanelSideBarLayout = <TPanelItemId extends string, TPanelItem>(prop
{ "section-tiles": renderFirstItemsLevelAsTiles },
)}
>
<PanelSideBar<TPanelItemId, TPanelItem> isIconShownOnSidebarCollapse={isIconShownOnSidebarCollapse} />
{collapsible && !useToggleButton && (
<PanelSideBarToggle
onClick={toggleSidebar}
toggled={!isSidebarOpen}
isIconShownOnSidebarCollapse={isIconShownOnSidebarCollapse}
/>
{!excludeSibebarMenu && (
<>
<PanelSideBar<TPanelItemId, TPanelItem> isIconShownOnSidebarCollapse={isIconShownOnSidebarCollapse} />
{collapsible && !useToggleButton && (
<PanelSideBarToggle
onClick={toggleSidebar}
toggled={!isSidebarOpen}
isIconShownOnSidebarCollapse={isIconShownOnSidebarCollapse}
/>
)}
</>
)}
<PanelSideBarLayoutContent footer={footer} isIconShownOnSidebarCollapse={isIconShownOnSidebarCollapse}>
<PanelSideBarLayoutContent
excludeSibebarMenu={excludeSibebarMenu}
footer={footer}
isIconShownOnSidebarCollapse={isIconShownOnSidebarCollapse}
>
{children}
</PanelSideBarLayoutContent>
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ import { usePanelSideBarContext } from "./PanelSideBar/Context/PanelSideBarConte
interface PanelSideBarLayoutContentProps extends PropsWithChildren {
footer?: ReactNode;
isIconShownOnSidebarCollapse: boolean;
excludeSibebarMenu: boolean;
}

export const PanelSideBarLayoutContent = (props: PanelSideBarLayoutContentProps) => {
const { children, footer, isIconShownOnSidebarCollapse } = props;
const { children, footer, isIconShownOnSidebarCollapse, excludeSibebarMenu } = props;
const { mainContentBodyRef } = usePanelSideBarContext();

return (
<section
ref={mainContentBodyRef}
id="main-content-body"
className={classNames("content", { "show-icons": isIconShownOnSidebarCollapse })}
className={classNames("content", { "show-icons": isIconShownOnSidebarCollapse }, { "exclude-sidebar-menu": excludeSibebarMenu })}
>
<main className="container-fluid">{children}</main>
<footer hidden={!footer} className="py-4 bg-light mt-auto">
Expand Down
24 changes: 17 additions & 7 deletions src/lib/Layout/PanelSideBarLayout/PanelSideBarNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { faBars } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ReactNode } from "react";
import { Nav, NavItem } from "reactstrap";
import { usePanelSideBarContext } from "./PanelSideBar/Context/PanelSideBarContext";
import classNames from "classnames";
import { SidebarProps } from "./PanelSideBar/Context/PanelSideBarContextProps";

interface PanelSidebarNavbarProps {
export interface PanelSidebarNavbarInternalProps extends Pick<Partial<SidebarProps>, "theme" | "toggleSidebar"> {
/**
* The brand content shown on the top navigation bar.
*/
Expand All @@ -25,9 +25,13 @@ interface PanelSidebarNavbarProps {
useToggleButton?: boolean;
}

const PanelSidebarNavbar = (props: PanelSidebarNavbarProps) => {
const { brand, navbarRightItems, navbarLeftItems, useToggleButton } = props;
const { toggleSidebar, theme } = usePanelSideBarContext();
const PanelSidebarNavbarInternal = (props: PanelSidebarNavbarInternalProps) => {
const { brand, navbarRightItems, navbarLeftItems, useToggleButton, toggleSidebar, theme } = props;

if (useToggleButton && !toggleSidebar) {
throw new Error("You must provide the toggleSidebar function when useToggleButton is true.");
}

return (
<nav
id="nav-top"
Expand All @@ -40,7 +44,7 @@ const PanelSidebarNavbar = (props: PanelSidebarNavbarProps) => {
>
<div className="navbar-brand">{brand}</div>
{useToggleButton && (
<button id="sidebar-toggle" className="btn btn-link btn-sm order-0 me-lg-0" onClick={() => toggleSidebar()}>
<button id="sidebar-toggle" className="btn btn-link btn-sm order-0 me-lg-0" onClick={() => toggleSidebar && toggleSidebar()}>
<FontAwesomeIcon icon={faBars} size="2x" />
</button>
)}
Expand All @@ -64,4 +68,10 @@ const PanelSidebarNavbar = (props: PanelSidebarNavbarProps) => {
);
};

export { PanelSidebarNavbar };
export type PanelSidebarNavbarProps = Omit<PanelSidebarNavbarInternalProps, "toggleSidebar" | "useToggleButton">;

const PanelSidebarNavbar = (props: PanelSidebarNavbarProps) => {
return <PanelSidebarNavbarInternal {...props} useToggleButton={false} />;
};

export { PanelSidebarNavbarInternal, PanelSidebarNavbar };
4 changes: 4 additions & 0 deletions styles/Layout/_PanelSideBarLayout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ section.content:first-of-type {
justify-content: space-between;
display: flex;
position: relative;

&.exclude-sidebar-menu {
margin-left: 0rem;
}
}

#side-nav.panel-layout {
Expand Down
Loading