Skip to content

Commit 91f9227

Browse files
authored
feat(sideNav): Adds support for grouped nav with headers and dividers. (#4754)
* feat(sideNav): Adds support for grouped nav with headers and dividers. * Updates that address feedback and hopefully make things more efficient and sound. * Updates code logic per feedback.
1 parent 362c407 commit 91f9227

File tree

1 file changed

+46
-14
lines changed
  • packages/documentation-framework/components/sideNav

1 file changed

+46
-14
lines changed

packages/documentation-framework/components/sideNav/sideNav.js

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@ import {
44
Label,
55
Nav,
66
NavList,
7+
NavGroup,
78
NavExpandable,
89
PageContextConsumer,
910
capitalize,
1011
Flex,
11-
FlexItem
12+
FlexItem,
13+
Divider
1214
} from '@patternfly/react-core';
1315
import { css } from '@patternfly/react-styles';
1416
import { Location } from '@reach/router';
17+
18+
const DIVIDER_STYLES = {
19+
marginTop: 'var(--pf-t--global--spacer--md)',
20+
marginBottom: 'var(--pf-t--global--spacer--md)'
21+
};
1522
import { makeSlug } from '../../helpers';
1623
import globalBreakpointXl from '@patternfly/react-tokens/dist/esm/t_global_breakpoint_xl';
1724
import { trackEvent } from '../../helpers';
@@ -163,20 +170,45 @@ export const SideNav = ({ groupedRoutes = {}, navItems = [] }) => {
163170
}
164171
}, []);
165172

173+
const groupedItems = React.useMemo(() =>
174+
(navItems || []).filter(entry => entry && entry.title), [navItems]);
175+
const ungroupedItems = React.useMemo(() =>
176+
(navItems || []).filter(entry => entry && !entry.title), [navItems]);
177+
178+
const renderNavItem = React.useCallback((item) => {
179+
if (!item) return null;
180+
181+
return item.section ? (
182+
<Location key={item.section}>
183+
{({ location }) => ExpandableNav({ groupedRoutes, location, section: item.section })}
184+
</Location>
185+
) : NavItem({
186+
key: item.href || `nav-item-${Math.random()}`,
187+
text: item.text || (item.href ? capitalize(item.href.replace(/\//g, '').replace(/-/g, ' ')) : 'Untitled'),
188+
href: item.href
189+
});
190+
}, [groupedRoutes]);
191+
166192
return (
167193
<Nav aria-label="Side Nav" theme="light">
168-
<NavList className="ws-side-nav-list">
169-
{navItems.map(({ section, text, href }) =>
170-
section ? (
171-
<Location key={section}>{({ location }) => ExpandableNav({ groupedRoutes, location, section })}</Location>
172-
) : (
173-
NavItem({
174-
text: text || capitalize(href.replace(/\//g, '').replace(/-/g, ' ')),
175-
href: href
176-
})
177-
)
178-
)}
179-
</NavList>
194+
{/* Render grouped items */}
195+
{groupedItems.map((group) => (
196+
<React.Fragment key={group.title}>
197+
<NavGroup title={group.title}>
198+
<NavList className="ws-side-nav-list" aria-label={`${group.title} navigation`}>
199+
{group.items.map(renderNavItem)}
200+
</NavList>
201+
</NavGroup>
202+
{group.hasDivider && <Divider style={DIVIDER_STYLES} />}
203+
</React.Fragment>
204+
))}
205+
206+
{/* Render ungrouped items - this handles the current flat structure */}
207+
{ungroupedItems.length > 0 && (
208+
<NavList className="ws-side-nav-list">
209+
{ungroupedItems.map(renderNavItem)}
210+
</NavList>
211+
)}
180212
</Nav>
181213
);
182-
};
214+
};

0 commit comments

Comments
 (0)