Skip to content

Commit 1beb389

Browse files
committed
feat(sideNav): Adds support for grouped nav with headers and dividers.
1 parent 4b5a372 commit 1beb389

File tree

1 file changed

+75
-12
lines changed
  • packages/documentation-framework/components/sideNav

1 file changed

+75
-12
lines changed

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

Lines changed: 75 additions & 12 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,76 @@ export const SideNav = ({ groupedRoutes = {}, navItems = [] }) => {
163170
}
164171
}, []);
165172

173+
const processedItems = React.useMemo(() => {
174+
const result = [];
175+
let currentGroup = null;
176+
let groupItems = [];
177+
178+
for (let i = 0; i < navItems.length; i++) {
179+
const item = navItems[i];
180+
181+
if (item.header) {
182+
if (currentGroup) {
183+
result.push({ type: 'group', title: currentGroup, items: groupItems });
184+
}
185+
currentGroup = item.header;
186+
groupItems = [];
187+
} else if (item.divider) {
188+
if (currentGroup) {
189+
result.push({ type: 'group', title: currentGroup, items: groupItems });
190+
currentGroup = null;
191+
groupItems = [];
192+
}
193+
result.push({ type: 'divider', key: item.divider });
194+
} else {
195+
currentGroup ? groupItems.push(item) : result.push({ type: 'item', ...item });
196+
}
197+
}
198+
199+
if (currentGroup) {
200+
result.push({ type: 'group', title: currentGroup, items: groupItems });
201+
}
202+
203+
return result;
204+
}, [navItems]);
205+
166206
return (
167207
<Nav aria-label="Side Nav" theme="light">
168208
<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-
)}
209+
{processedItems.map(processed => {
210+
if (processed.type === 'divider') {
211+
return <Divider key={processed.key} style={DIVIDER_STYLES} />;
212+
}
213+
214+
if (processed.type === 'group') {
215+
return (
216+
<NavGroup key={processed.title} title={processed.title}>
217+
{processed.items.map(item =>
218+
item.section ? (
219+
<Location key={item.section}>
220+
{({ location }) => ExpandableNav({ groupedRoutes, location, section: item.section })}
221+
</Location>
222+
) : NavItem({
223+
key: item.href,
224+
text: item.text || capitalize(item.href.replace(/\//g, '').replace(/-/g, ' ')),
225+
href: item.href
226+
})
227+
)}
228+
</NavGroup>
229+
);
230+
}
231+
232+
return processed.section ? (
233+
<Location key={processed.section}>
234+
{({ location }) => ExpandableNav({ groupedRoutes, location, section: processed.section })}
235+
</Location>
236+
) : NavItem({
237+
key: processed.href,
238+
text: processed.text || capitalize(processed.href.replace(/\//g, '').replace(/-/g, ' ')),
239+
href: processed.href
240+
});
241+
})}
179242
</NavList>
180243
</Nav>
181244
);
182-
};
245+
};

0 commit comments

Comments
 (0)