Skip to content

Commit f13bb5c

Browse files
Rúben CarvalhoRuben Carvalho
andauthored
feat: Add new side navigation item type "section-group" (#662)
Co-authored-by: Ruben Carvalho <[email protected]>
1 parent 780d0ca commit f13bb5c

File tree

9 files changed

+337
-14
lines changed

9 files changed

+337
-14
lines changed

pages/side-navigation/permutations.page.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,33 @@ const permutations = createPermutations<SideNavigationProps>([
4747
},
4848
],
4949
},
50+
{
51+
type: 'section-group',
52+
title: 'Section group title',
53+
items: [
54+
{
55+
type: 'link',
56+
text: 'Overview',
57+
href: '#/page1',
58+
},
59+
{
60+
type: 'section',
61+
text: 'Contributions',
62+
items: [
63+
{
64+
type: 'link',
65+
text: 'Design',
66+
href: '#/design',
67+
},
68+
{
69+
type: 'link',
70+
text: 'Dev',
71+
href: '#/dev',
72+
},
73+
],
74+
},
75+
],
76+
},
5077
{
5178
type: 'expandable-link-group',
5279
text: 'Getting started',
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React from 'react';
4+
import SideNavigation, { SideNavigationProps } from '~components/side-navigation';
5+
import Badge from '~components/badge';
6+
7+
const items: SideNavigationProps.Item[] = [
8+
{
9+
type: 'link',
10+
text: 'Page',
11+
href: '#/page1',
12+
},
13+
{
14+
type: 'divider',
15+
},
16+
{
17+
type: 'section-group',
18+
title: 'Section header',
19+
items: [
20+
{
21+
type: 'link',
22+
text: 'Page',
23+
href: '#/page1',
24+
},
25+
{
26+
type: 'link',
27+
text: 'Page',
28+
href: '#/page1',
29+
},
30+
],
31+
},
32+
{ type: 'divider' },
33+
{
34+
type: 'section-group',
35+
title: 'Section group title',
36+
items: [
37+
{
38+
type: 'link',
39+
text: 'Overview',
40+
href: '#/page1',
41+
},
42+
{
43+
type: 'section',
44+
text: 'Contributions',
45+
items: [
46+
{
47+
type: 'link',
48+
text: 'Design',
49+
href: '#/design',
50+
},
51+
{
52+
type: 'link',
53+
text: 'Dev',
54+
href: '#/dev',
55+
},
56+
],
57+
},
58+
{
59+
type: 'link',
60+
text: 'Page',
61+
href: '#/page1',
62+
},
63+
{
64+
type: 'expandable-link-group',
65+
text: 'Expandable link group',
66+
href: '#/exp-link-group',
67+
items: [
68+
{
69+
type: 'link',
70+
text: 'Page 9',
71+
href: '#/page9',
72+
},
73+
{
74+
type: 'link',
75+
text: 'Page 10',
76+
href: '#/page10',
77+
},
78+
{
79+
type: 'expandable-link-group',
80+
text: 'Expandable link group',
81+
href: '#/exp-link-group-inner',
82+
items: [
83+
{
84+
type: 'link',
85+
text: 'Page 11',
86+
href: '#/page11',
87+
},
88+
{
89+
type: 'link',
90+
text: 'Page 12',
91+
href: '#/page12',
92+
},
93+
],
94+
},
95+
],
96+
},
97+
{
98+
type: 'link',
99+
text: 'Page',
100+
href: '#/page1',
101+
},
102+
{
103+
type: 'link-group',
104+
text: 'Link group',
105+
href: '#/link-group',
106+
items: [
107+
{
108+
type: 'link',
109+
text: 'Page 9',
110+
href: '#/page9',
111+
},
112+
{
113+
type: 'link',
114+
text: 'Page 10',
115+
href: '#/page10',
116+
},
117+
],
118+
},
119+
{
120+
type: 'link',
121+
text: 'Page',
122+
href: '#/page1',
123+
},
124+
],
125+
},
126+
{ type: 'divider' },
127+
{
128+
type: 'section-group',
129+
title: 'H3 Section Header',
130+
items: [
131+
{
132+
type: 'link',
133+
text: 'Page',
134+
href: '#/page1',
135+
},
136+
{
137+
type: 'section',
138+
text: 'Contributions',
139+
items: [
140+
{
141+
type: 'link',
142+
text: 'Design',
143+
href: '#/design',
144+
},
145+
{
146+
type: 'link',
147+
text: 'Dev',
148+
href: '#/dev',
149+
},
150+
],
151+
},
152+
],
153+
},
154+
{ type: 'link', text: 'Notifications', href: '#/notifications', info: <Badge color="red">23</Badge> },
155+
{ type: 'link', text: 'Documentation', href: '#', external: true, externalIconAriaLabel: 'Opens in a new tab' },
156+
];
157+
158+
export default function SideNavigationPage() {
159+
return (
160+
<>
161+
<h1>Side navigation with section-groups</h1>
162+
<SideNavigation
163+
activeHref="#/"
164+
header={{
165+
href: '#/',
166+
text: 'Header title',
167+
}}
168+
items={items}
169+
/>
170+
</>
171+
);
172+
}

pages/side-navigation/simple.page.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,36 @@ const ITEMS: SideNavigationProps.Item[] = [
5858
},
5959
],
6060
},
61+
{ type: 'divider' },
62+
{
63+
type: 'section-group',
64+
title: 'Section Group',
65+
items: [
66+
{
67+
type: 'link',
68+
text: 'Overview',
69+
href: '#/page6',
70+
},
71+
{
72+
type: 'expandable-link-group',
73+
text: 'Expandable link group',
74+
href: '#/exp-link-group',
75+
items: [
76+
{
77+
type: 'link',
78+
text: 'Page 9',
79+
href: '#/page9',
80+
},
81+
{
82+
type: 'link',
83+
text: 'Page 10',
84+
href: '#/page10',
85+
},
86+
],
87+
},
88+
],
89+
},
90+
{ type: 'divider' },
6191
{
6292
type: 'expandable-link-group',
6393
text: 'Expandable link group',

src/__tests__/__snapshots__/documenter.test.ts.snap

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10574,7 +10574,7 @@ to the href of the clicked item so you'll have to do it yourself.
1057410574
Object {
1057510575
"name": "type",
1057610576
"optional": true,
10577-
"type": "\\"expandable-link-group\\" | \\"link\\" | \\"link-group\\"",
10577+
"type": "\\"expandable-link-group\\" | \\"link\\" | \\"link-group\\" | \\"section-header\\"",
1057810578
},
1057910579
],
1058010580
"type": "object",
@@ -10678,6 +10678,13 @@ Object that represents a section within the navigation.
1067810678
Although there is no technical limitation to the nesting level,
1067910679
our UX recommendation is to use only one level.
1068010680

10681+
#### Section Group
10682+
Aggregates a set of items that are conceptually related to each other, and can be displayed under a single heading to provide further organization.
10683+
You can nest sections, links, link groups and expandable link groups within a section group depending on your information architecture needs.
10684+
- \`type\`: \`'section-group'\`.
10685+
- \`title\` (string) - Specifies the text to display as a title of the section group.
10686+
- \`items\` (array) - Specifies the content of the section header group. You can use \`Section\`, \`Link\`, \`LinkGroup\`, \`ExpandableLinkGroup\`.
10687+
1068110688
#### LinkGroup
1068210689
Object that represents a group of links.
1068310690
- \`type\`: \`'link-group'\`.

src/side-navigation/__tests__/side-navigation.test.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ describe('SideNavigation', () => {
169169
const wrapper = renderSideNavigation({ header: { text: 'Console', href: '#something' } });
170170
expect(wrapper.findHeaderLink()!.getElement()).toHaveTextContent('Console');
171171
});
172-
173172
it('renders the header in a <h2>', () => {
174173
const wrapper = renderSideNavigation({ header: { text: 'Console', href: '#something' } });
174+
expect(wrapper.findHeader()!.getElement()!.tagName).toBe('H2');
175175
expect(wrapper.find('h2')!.getElement()).toHaveTextContent('Console');
176176
});
177177

@@ -189,6 +189,19 @@ describe('SideNavigation', () => {
189189
});
190190
});
191191

192+
describe('Section Group', () => {
193+
it('has specified title', () => {
194+
const wrapper = renderSideNavigation({ items: [{ type: 'section-group', title: 'Section Group', items: [] }] });
195+
expect(wrapper.findItemByIndex(1)?.findSectionGroupTitle()!.getElement()).toHaveTextContent('Section Group');
196+
});
197+
198+
it('renders the section group title in a <h3>', () => {
199+
const wrapper = renderSideNavigation({ items: [{ type: 'section-group', title: 'Section Group', items: [] }] });
200+
expect(wrapper.findItemByIndex(1)?.findSectionGroup()!.getElement()!.children[0]!.tagName).toBe('H3');
201+
expect(wrapper.find('h3')!.getElement()).toHaveTextContent('Section Group');
202+
});
203+
});
204+
192205
describe('Link', () => {
193206
it('has specified text', () => {
194207
const wrapper = renderSideNavigation({ items: [{ type: 'link', text: 'Page 1', href: '#something' }] });

src/side-navigation/interfaces.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ export interface SideNavigationProps extends BaseComponentProps {
6060
* Although there is no technical limitation to the nesting level,
6161
* our UX recommendation is to use only one level.
6262
*
63+
* #### Section Group
64+
* Aggregates a set of items that are conceptually related to each other, and can be displayed under a single heading to provide further organization.
65+
* You can nest sections, links, link groups and expandable link groups within a section group depending on your information architecture needs.
66+
* - `type`: `'section-group'`.
67+
* - `title` (string) - Specifies the text to display as a title of the section group.
68+
* - `items` (array) - Specifies the content of the section header group. You can use `Section`, `Link`, `LinkGroup`, `ExpandableLinkGroup`.
69+
*
6370
* #### LinkGroup
6471
* Object that represents a group of links.
6572
* - `type`: `'link-group'`.
@@ -142,6 +149,11 @@ export namespace SideNavigationProps {
142149
defaultExpanded?: boolean;
143150
}
144151

152+
export interface SectionGroup {
153+
type: 'section-group';
154+
title: string;
155+
items: ReadonlyArray<Section | Link | LinkGroup | ExpandableLinkGroup>;
156+
}
145157
export interface LinkGroup {
146158
type: 'link-group';
147159
text: string;
@@ -157,7 +169,7 @@ export namespace SideNavigationProps {
157169
defaultExpanded?: boolean;
158170
}
159171

160-
export type Item = Divider | Link | Section | LinkGroup | ExpandableLinkGroup;
172+
export type Item = Divider | Link | Section | LinkGroup | ExpandableLinkGroup | SectionGroup;
161173

162174
export interface ChangeDetail {
163175
item: Section | ExpandableLinkGroup;
@@ -168,7 +180,7 @@ export namespace SideNavigationProps {
168180
export interface FollowDetail extends BaseNavigationDetail {
169181
text?: string;
170182
href: string;
171-
type?: 'link' | 'link-group' | 'expandable-link-group';
183+
type?: 'link' | 'link-group' | 'expandable-link-group' | 'section-header';
172184
info?: React.ReactNode;
173185
}
174186
}

0 commit comments

Comments
 (0)