Skip to content

Commit

Permalink
Add possibility do not render tiles or to render tiles as a link, rem…
Browse files Browse the repository at this point in the history
…ove unneeded code (#53)
  • Loading branch information
manni497 authored Mar 8, 2024
1 parent 6242b4b commit c050d19
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 58 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Possibility to decide if render first nesting level of menuItems as tiles (default) or not
- Possibility to render tiles as button(default) or as links
- Possibility to define a default active panel used if no active panel is found dynamically

## [3.2.1] - 2024-02-01

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ export interface PanelSideBarContextProps<TPanelItem> {
* The context theme
*/
theme?: "light";
/**
* Boolean indicating if you want to render first items level as icons or directly as menu entries
*/
renderFirstItemsLevelAsTiles?: boolean;

/**
* Boolean indicating if you want to render first level items as links or as button
*/
renderTilesAsLinks?: boolean;

/**
* The default active panel id that will be taken if no active panel is dinamically found
*/
defaultActivePanelId?: string;
}

export const PanelSideBarContext = createContext<PanelSideBarContextProps<any> | null>(null);
Expand All @@ -86,6 +100,9 @@ export interface PanelSideBarMenuProviderProps<TPanelItem>
| "topBarLeftCustomItems"
| "localItems"
| "theme"
| "renderFirstItemsLevelAsTiles"
| "renderTilesAsLinks"
| "defaultActivePanelId"
> {
/**
* The children elements.
Expand All @@ -105,13 +122,16 @@ export const PanelSideBarProvider = <TPanelItem,>(props: PanelSideBarMenuProvide
userDropDownMenuToggle,
topBarRightCustomItems,
topBarLeftCustomItems,
renderFirstItemsLevelAsTiles = true,
renderTilesAsLinks = false,
theme = "light",
defaultActivePanelId,
} = props;

const activePanel = globalItems.find((x) =>
x.children ? x.children.find((y) => (y.children ? y.children.find((s) => s.active) : y.active)) : x.active,
);
const firstActivePanel = activePanel ?? globalItems.find((x) => x.id);
const firstActivePanel = activePanel ?? globalItems.find((x) => (defaultActivePanelId ? x.id === defaultActivePanelId : x.id));

const getActivePanelId = () => localItems?.at(0)?.id ?? firstActivePanel?.id ?? "";

Expand Down Expand Up @@ -155,6 +175,8 @@ export const PanelSideBarProvider = <TPanelItem,>(props: PanelSideBarMenuProvide
topBarLeftCustomItems,
brand,
theme,
renderFirstItemsLevelAsTiles,
renderTilesAsLinks,
}}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ export interface PanelSideBarItemProps {
depth?: number;
active?: boolean;
toggledItemIds: string[];
toggledSidebar: boolean;
}

const PanelSideBarItem = (props: PanelSideBarItemProps) => {
const { depth = 0, children: item, LinkRenderer, onClick, toggledItemIds = [], toggledSidebar } = props;
const { depth = 0, children: item, LinkRenderer, onClick, toggledItemIds = [] } = props;

const hasitem = !!item.children?.length;
const isActive = item.children?.find((s) => s.active) || item.active;
Expand Down Expand Up @@ -88,7 +87,6 @@ const PanelSideBarItem = (props: PanelSideBarItemProps) => {
depth={depth + 1}
active={item.active}
toggledItemIds={toggledItemIds}
toggledSidebar={toggledSidebar}
/>
))}
</Collapse>
Expand Down
130 changes: 80 additions & 50 deletions src/lib/Layout/PanelSideBarLayout/PanelSideBar/PanelSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ import { usePanelSideBarContext } from "./Context/PanelSideBarContext";
import { PanelItem } from "./Definitions/PanelItem";
import { PanelSideBarItem } from "./PanelSideBarItem";

interface PanelSidebarProps {
toggledSidebar: boolean;
}

export const PanelSideBar = (props: PanelSidebarProps) => {
const { toggledSidebar } = props;
export const PanelSideBar = () => {
const {
activePanelId,
globalItems,
Expand All @@ -19,55 +14,90 @@ export const PanelSideBar = (props: PanelSidebarProps) => {
setActivePanel,
toggledMenuItemIds,
toggleMenuItem,
renderFirstItemsLevelAsTiles,
renderTilesAsLinks,
} = usePanelSideBarContext();
const panelItems = localItems.concat(globalItems);

if (globalItems.find((x) => !x.icon) || localItems.find((x) => !x.icon)) {
throw new Error("Outer panel icon is required");
}
if (renderFirstItemsLevelAsTiles) {
if (globalItems.find((x) => !x.icon) || localItems.find((x) => !x.icon)) {
throw new Error("Outer panel icon is required");
}

const activePanel: PanelItem | undefined = panelItems.find((x) => x.id === activePanelId);
const activePanel: PanelItem | undefined = panelItems.find((x) => x.id === activePanelId);
const ButtonIcon = (props: { item: PanelItem }) => {
const {
item: { disabled, icon, onClick, id, title },
} = props;
return (
<Button
key={id}
color="primary"
outline
className={classNames("tile", { active: activePanelId === id })}
onClick={() => {
if (!renderTilesAsLinks) {
if (onClick) {
onClick();
} else {
setActivePanel(id);
}
}
}}
title={typeof title == "string" ? String(title) : ""}
disabled={disabled}
>
{icon && <FontAwesomeIcon icon={icon} size="lg" fixedWidth />}
</Button>
);
};

const panelItemsRenderer = (items: PanelItem[]) =>
items?.map(({ disabled, icon, onClick, id, title }) => (
<Button
key={id}
color="primary"
outline
className={classNames("tile", { active: activePanelId === id })}
onClick={() => {
if (onClick) {
onClick();
} else {
setActivePanel(id);
}
}}
title={typeof title == "string" ? String(title) : ""}
disabled={disabled}
>
{icon && <FontAwesomeIcon icon={icon} size="lg" fixedWidth />}
</Button>
));
const panelItemsRenderer = (items: PanelItem[]) =>
items?.map((item) =>
renderTilesAsLinks ? (
<LinkRenderer item={item}>
<ButtonIcon item={item} />
</LinkRenderer>
) : (
<ButtonIcon item={item} />
),
);

return (
<nav id="side-nav" className="panel-layout">
<div className="side-nav__tiles">
{panelItemsRenderer(globalItems)}
{panelItemsRenderer(localItems)}
</div>
return (
<nav id="side-nav" className="panel-layout">
<div className="side-nav__tiles">
{panelItemsRenderer(globalItems)}
{panelItemsRenderer(localItems)}
</div>

<div className="side-nav__items">
{activePanel?.children?.map((item) => (
<PanelSideBarItem
key={item.id}
children={item}
LinkRenderer={LinkRenderer}
onClick={(menuItem) => toggleMenuItem(menuItem)}
toggledItemIds={toggledMenuItemIds}
toggledSidebar={toggledSidebar}
/>
))}
</div>
</nav>
);
<div className="side-nav__items">
{activePanel?.children?.map((item) => (
<PanelSideBarItem
key={item.id}
children={item}
LinkRenderer={LinkRenderer}
onClick={(menuItem) => toggleMenuItem(menuItem)}
toggledItemIds={toggledMenuItemIds}
/>
))}
</div>
</nav>
);
} else {
return (
<nav id="side-nav" className="panel-layout">
<div className="side-nav__items">
{panelItems?.map((item) => (
<PanelSideBarItem
key={item.id}
children={item}
LinkRenderer={LinkRenderer}
onClick={(menuItem) => toggleMenuItem(menuItem)}
toggledItemIds={toggledMenuItemIds}
/>
))}
</div>
</nav>
);
}
};
11 changes: 9 additions & 2 deletions src/lib/Layout/PanelSideBarLayout/PanelSideBarLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const PanelSideBarLayout = (props: PanelSideBarLayoutProps) => {
userDropDownMenuToggle,
topBarRightCustomItems = [],
topBarLeftCustomItems = [],
renderFirstItemsLevelAsTiles,
} = usePanelSideBarContext();

return (
Expand Down Expand Up @@ -75,8 +76,14 @@ export const PanelSideBarLayout = (props: PanelSideBarLayoutProps) => {
</Nav>
</nav>

<section className={classNames({ toggled: !isOpen })}>
<PanelSideBar toggledSidebar={isOpen} />
<section
className={classNames(
{ toggled: !isOpen },
{ "section-no-tiles": !renderFirstItemsLevelAsTiles },
{ "section-tiles": renderFirstItemsLevelAsTiles },
)}
>
<PanelSideBar />
{collapsible && <PanelSideBarToggle onClick={toggleSidebar} toggled={!isOpen} />}
<PanelSideBarLayoutContent footer={footer ?? contextFooter}>{children}</PanelSideBarLayoutContent>
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const PanelSideBarLayoutContent = (props: PanelSideBarLayoutContentProps)
const { children, footer } = props;

return (
<section className="content">
<section id="main-content-body" className="content">
<main className="container-fluid">{children}</main>
<footer className="py-4 bg-light mt-auto">
<div className="mx-4">
Expand Down
23 changes: 22 additions & 1 deletion styles/Layout/PanelSideBarLayout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ section.content:first-of-type {
@include media-breakpoint-up(xs) {
$toggled-width: #{$tile-size + $slim-scrollbar-base-width};

section.toggled {
.section-tiles.toggled {
> #side-nav {
transition: $sidebar-transition;
width: #{$tile-size + $slim-scrollbar-base-width};
Expand All @@ -266,4 +266,25 @@ section.content:first-of-type {
}
}
}

.section-no-tiles.toggled {
> #side-nav {
transition: $sidebar-transition;
width: #{$slim-scrollbar-base-width};
}

> #side-nav-toggle {
transition: $sidebar-transition;
left: 0px;
}

> section.content:first-of-type {
transition: #{margin $sidebar-transition};
margin-left: #{$toggle-base-width};

.dropdown-toggle::after {
display: none;
}
}
}
}

0 comments on commit c050d19

Please sign in to comment.