Skip to content

Commit e43c733

Browse files
author
Leupp, Joel
committed
feat: resolve findings from review
1 parent db6af71 commit e43c733

File tree

15 files changed

+192
-69
lines changed

15 files changed

+192
-69
lines changed

docs/changelog.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
1212
- **⚠️Experimental**: Adding example React app with Vite.
1313

1414
- [Documentation](guide/angular.md) for using web components with Angular's standalone bootstrapping
15-
- `ActiveSidebarItemGroupDirective` and `ActiveSidebarItemDirective`: Added angular sidbar helper
16-
directives
15+
- `ActiveSidebarItemGroupDirective` and `ActiveSidebarItemDirective`: Added optional angular sidebar
16+
helper directives. See the [Angular guide](guide/angular.md) for more information.
1717
- Added nested sidbar menu to the angular demo application to showcase the helper directives
1818
- `six-header-dropdown`: Added `filter` and `filterPlaceholder` properties.
1919
- `six-header-menu-button`: Added `caret`, `disabled`, `loading`, `submit` and `reset` properties.

docs/components/six-sidebar.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ six-sidebar allows to add a static sidebar to the left or right of the `six-root
1717
<six-sidebar-item value="data" icon="analytics" disabled="true">Data</six-sidebar-item>
1818
<six-sidebar-item value="history" icon="history">History</six-sidebar-item>
1919
<six-sidebar-item-group icon="settings" name="Settings">
20-
<six-sidebar-item value="data" selected>Data</six-sidebar-item>
21-
<six-sidebar-item value="history">History</six-sidebar-item>
20+
<six-sidebar-item value="settingA" selected>Setting A</six-sidebar-item>
21+
<six-sidebar-item value="settingB">Setting B</six-sidebar-item>
22+
<six-sidebar-item-group icon="settings" name="Nested Settings">
23+
<six-sidebar-item value="sectionA" selected>Section A</six-sidebar-item>
24+
<six-sidebar-item value="sectionB">Section B</six-sidebar-item>
25+
</six-sidebar-item-group>
2226
</six-sidebar-item-group>
2327
</six-sidebar-item-group>
2428
<six-sidebar-item-group icon="task"

docs/examples/docs-demo-six-sidebar-0.vue

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
<six-sidebar-item value="data" icon="analytics" disabled="true">Data</six-sidebar-item>
77
<six-sidebar-item value="history" icon="history">History</six-sidebar-item>
88
<six-sidebar-item-group icon="settings" name="Settings">
9-
<six-sidebar-item value="data" selected>Data</six-sidebar-item>
10-
<six-sidebar-item value="history">History</six-sidebar-item>
9+
<six-sidebar-item value="settingA" selected>Setting A</six-sidebar-item>
10+
<six-sidebar-item value="settingB">Setting B</six-sidebar-item>
11+
<six-sidebar-item-group icon="settings" name="Nested Settings">
12+
<six-sidebar-item value="sectionA" selected>Section A</six-sidebar-item>
13+
<six-sidebar-item value="sectionB">Section B</six-sidebar-item>
14+
</six-sidebar-item-group>
1115
</six-sidebar-item-group>
1216
</six-sidebar-item-group>
1317
<six-sidebar-item-group icon="task"

docs/guide/angular.md

+37
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,40 @@ Consult the
127127
[Angular example](https://github.com/six-group/six-webcomponents/tree/main/examples/angular) and the
128128
[source code documentation](https://github.com/six-group/six-webcomponents/blob/main/libraries/ui-library-angular/src/lib/form/six-form.directive.ts)
129129
of the `SixFormDirective` and for a more flexible alternative, the `SixFormUtilDirective`.
130+
131+
## Sidebar
132+
133+
The library provides Angular Router integration for the sidebar component through a set of
134+
directives that automatically manage the selection and expansion states based on the current route.
135+
136+
To enable router integration, add the `sixRouterLinkActive` attribute to the `six-sidebar`
137+
component. This activates three directives that work together:
138+
139+
- `ActiveSidebarDirective`: Enables route-based navigation in the sidebar
140+
- `ActiveSidebarItemDirective`: Automatically manages item selection based on the current route
141+
- `ActiveSidebarItemGroupDirective`: Automatically expands groups when they contain active routes
142+
143+
Example usage:
144+
145+
```html
146+
<!-- add sixRouterLinkActive to six-sidebar to include the sidebar helper directives -->
147+
<six-sidebar position="left" [open]="open" sixRouterLinkActive>
148+
<six-sidebar-item-group routerLink="/home" name="Home" icon="home"></six-sidebar-item-group>
149+
<six-sidebar-item-group routerLink="/form" name="Form" icon="assignment"></six-sidebar-item-group>
150+
<six-sidebar-item-group icon="settings" name="Settings">
151+
<six-sidebar-item routerLink="/settings/data" icon="analytics">Data</six-sidebar-item>
152+
<six-sidebar-item routerLink="/settings/history" icon="history">History</six-sidebar-item>
153+
</six-sidebar-item-group>
154+
</six-sidebar>
155+
```
156+
157+
When the router integration is enabled:
158+
159+
- Sidebar items are automatically selected when their route is active
160+
- Sidebar groups automatically expand when containing active routes
161+
- Manual selection state is preserved when no routes are active
162+
163+
Consult the
164+
[Angular example](https://github.com/six-group/six-webcomponents/tree/main/examples/angular) and the
165+
[source code documentation](https://github.com/six-group/six-webcomponents/blob/main/libraries/ui-library-angular/src/lib/sidebar/active-sidebar.directive.ts)
166+
of the `ActiveSidebarDirective`, `ActiveSidebarItemDirective` and `ActiveSidebarItemGroupDirective`.

docs/guide/upgrade-v5.md

+10
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ in the Angular example application, which covers most features.
9898
</six-button>
9999
```
100100

101+
## Angular specific upgrade (None Breaking Change)
102+
103+
- Angular Router integration for the `six-sidebar` component through a set of directives that
104+
automatically manage the selection and expansion states based on the current route.
105+
106+
To enable router integration, add the `sixRouterLinkActive` attribute to the `six-sidebar`
107+
component.
108+
109+
For more information and a usage example consult the [angular guide](angular.md#sidebar).
110+
101111
## Removed deprecated features (Breaking Change)
102112

103113
Refer to the _Removed_ section in the [changelog](../changelog.md).

examples/angular/src/app/components/left-sidebar/left-sidebar.component.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<six-sidebar position="left" [open]="open">
1+
<six-sidebar position="left" [open]="open" sixRouterLinkActive>
22
<six-sidebar-item-group routerLink="/home" name="Home" icon="home"></six-sidebar-item-group>
33
<six-sidebar-item-group routerLink="/form" name="Form" icon="assignment"></six-sidebar-item-group>
44
<six-sidebar-item-group routerLink="/alert" name="Alert" icon="notifications_active"></six-sidebar-item-group>

libraries/ui-library-angular/src/lib/sidebar/active-sidebar-item-group.directive.ts

-26
This file was deleted.

libraries/ui-library-angular/src/lib/sidebar/active-sidebar-item.directive.ts

-18
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { ContentChildren, Directive, HostBinding, HostListener, inject, QueryList } from '@angular/core';
2+
import { RouterLinkActive } from '@angular/router';
3+
import { SixSidebarItem, SixSidebarItemGroup } from '../stencil-generated/components';
4+
5+
/**
6+
* Enables Angular router integration for the six-sidebar component.
7+
*
8+
* When this directive is added to a six-sidebar component using the 'sixRouterLinkActive' attribute,
9+
* it activates automatic route-based selection for sidebar items and groups.
10+
*
11+
* @recommended Add this directive to enable automatic route-based navigation in sidebars.
12+
*
13+
* @example
14+
* ```html
15+
* <six-sidebar sixRouterLinkActive>
16+
* <six-sidebar-item routerLink="/home">Home</six-sidebar-item>
17+
* <six-sidebar-item-group>
18+
* <six-sidebar-item routerLink="/settings/profile">Profile</six-sidebar-item>
19+
* </six-sidebar-item-group>
20+
* </six-sidebar>
21+
* ```
22+
*/
23+
@Directive({
24+
selector: 'six-sidebar[sixRouterLinkActive]',
25+
})
26+
export class ActiveSidebarDirective {}
27+
28+
/**
29+
* Enhances six-sidebar-item with Angular router integration.
30+
*
31+
* This directive automatically manages the 'selected' state of sidebar items based on the current route.
32+
* When used with ActiveSidebarDirective, it switches from manual selection to route-based selection.
33+
*
34+
* @requires RouterLinkActive
35+
* @optional ActiveSidebarDirective - If present, enables route-based selection
36+
*/
37+
@Directive({
38+
selector: 'six-sidebar-item',
39+
hostDirectives: [RouterLinkActive],
40+
})
41+
export class ActiveSidebarItemDirective {
42+
private routerLinkActive = inject(RouterLinkActive);
43+
44+
private sidebarItem = inject(SixSidebarItem);
45+
private activeSidebarDirective = inject(ActiveSidebarDirective, { optional: true });
46+
47+
@HostBinding('selected')
48+
get selected() {
49+
if (this.activeSidebarDirective == null) {
50+
return this.sidebarItem.selected;
51+
} else {
52+
return this.routerLinkActive.isActive;
53+
}
54+
}
55+
}
56+
57+
/**
58+
* Enhances six-sidebar-item-group with Angular router integration.
59+
*
60+
* This directive automatically manages the 'open' state of sidebar groups based on the active route.
61+
* When a child route is active, the group automatically expands to show the active item.
62+
*
63+
* @requires RouterLinkActive
64+
* @optional ActiveSidebarDirective - If present, enables route-based expansion
65+
*/
66+
@Directive({
67+
selector: 'six-sidebar-item-group',
68+
hostDirectives: [RouterLinkActive],
69+
})
70+
export class ActiveSidebarItemGroupDirective {
71+
private routerLinkActive = inject(RouterLinkActive);
72+
private sidebarItemGroup = inject(SixSidebarItemGroup);
73+
private activeSidebarDirective = inject(ActiveSidebarDirective, { optional: true });
74+
75+
@ContentChildren(SixSidebarItem) private sidebarItems!: QueryList<SixSidebarItem>;
76+
77+
@HostBinding('open')
78+
get open() {
79+
if (this.activeSidebarDirective == null) {
80+
return this.sidebarItemGroup.open;
81+
}
82+
83+
if (this.sidebarItems?.length > 0) {
84+
return this.routerLinkActive.isActive ? true : this.sidebarItemGroup.open;
85+
}
86+
87+
return this.routerLinkActive.isActive;
88+
}
89+
}

libraries/ui-library-angular/src/lib/ui-library-angular.module.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ import { SwitchValueAccessor } from './control-value-accessors/switch-value-acce
2020
import { TimepickerValueAccessor } from './control-value-accessors/timepicker-value-accessor';
2121
import { ValidationMessagesService } from './services/validation-messages.service';
2222
import { SixRouterLinkDirective } from './link/six-router-link.directive';
23-
import { ActiveSidebarItemDirective } from './sidebar/active-sidebar-item.directive';
24-
import { ActiveSidebarItemGroupDirective } from './sidebar/active-sidebar-item-group.directive';
23+
import {
24+
ActiveSidebarDirective,
25+
ActiveSidebarItemDirective,
26+
ActiveSidebarItemGroupDirective,
27+
} from './sidebar/active-sidebar.directive';
2528

2629
@NgModule({
2730
declarations: [
@@ -56,6 +59,7 @@ import { ActiveSidebarItemGroupDirective } from './sidebar/active-sidebar-item-g
5659
// sidebar helpers
5760
ActiveSidebarItemDirective,
5861
ActiveSidebarItemGroupDirective,
62+
ActiveSidebarDirective,
5963
],
6064
imports: [],
6165
exports: [
@@ -90,6 +94,7 @@ import { ActiveSidebarItemGroupDirective } from './sidebar/active-sidebar-item-g
9094
// sidebar helpers
9195
ActiveSidebarItemDirective,
9296
ActiveSidebarItemGroupDirective,
97+
ActiveSidebarDirective,
9398
],
9499
})
95100
export class UiLibraryAngularModule {

libraries/ui-library-angular/src/public-api.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Public API Surface of ui-library-angular
33
*/
44

5+
import { ActiveSidebarDirective } from './lib/sidebar/active-sidebar.directive';
6+
57
export * from './lib/ui-library-angular.module';
68

79
// proxies
@@ -30,8 +32,7 @@ export * from './lib/form/six-form.directive';
3032
export * from './lib/link/six-router-link.directive';
3133

3234
// sidbar helpers
33-
export * from './lib/sidebar/active-sidebar-item.directive';
34-
export * from './lib/sidebar/active-sidebar-item-group.directive';
35+
export * from './lib/sidebar/active-sidebar.directive';
3536

3637
// services
3738
export * from './lib/services/validation-messages.service';

libraries/ui-library/src/components/six-sidebar-item-group/six-sidebar-item-group.scss

+8-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
}
66

77
.six-sidebar-item-group {
8-
--horizontal-padding: var(--six-spacing-x-large);
8+
--horizontal-padding: var(--six-spacing-large);
9+
&::part(content) {
10+
padding: var(--six-spacing-medium) 0 var(--six-spacing-medium) var(--six-spacing-medium) !important;
11+
}
912
}
1013

1114
.six-sidebar-item-group--childless::part(content) {
@@ -14,7 +17,8 @@
1417

1518
.six-sidebar-item-group--subgroup::part(header) {
1619
background-color: transparent !important;
17-
--horizontal-padding: var(--six-spacing-large);
20+
padding: var(--six-spacing-small) var(--six-spacing-large) var(--six-spacing-small) var(--six-spacing-medium) !important;
21+
margin-left: var(--six-spacing-xx-small);
1822
}
1923

2024
.six-sidebar-item-group__header-icon {
@@ -24,11 +28,12 @@
2428

2529
.six-sidebar-details__header {
2630
display: flex;
31+
align-items: center;
2732
overflow-wrap: anywhere;
2833
}
2934

3035
.six-sidebar-details__header-icon {
31-
margin-right: 1em;
36+
margin-right: var(--six-spacing-medium);
3237
}
3338

3439
.six-sidebar-details__link {

libraries/ui-library/src/components/six-sidebar-item-group/six-sidebar-item-group.tsx

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Component, Element, h, Prop, State } from '@stencil/core';
22
import { hasSlot } from '../../utils/slot';
3+
import { SixDetailsCustomEvent } from '../../components';
34

45
/**
56
* @since 1.0
@@ -61,6 +62,16 @@ export class SixSidebarItemGroup {
6162
return this.href != null && !this.hasItems;
6263
}
6364

65+
private handleDetailsShow = (event: SixDetailsCustomEvent<undefined>) => {
66+
event.stopPropagation();
67+
this.open = true;
68+
};
69+
70+
private handleDetailsHide = (event: SixDetailsCustomEvent<undefined>) => {
71+
event.stopPropagation();
72+
this.open = false;
73+
};
74+
6475
private provideSlot = (name: string) => {
6576
if (this.summaryIconHasContent) {
6677
return (
@@ -94,12 +105,8 @@ export class SixSidebarItemGroup {
94105
inline={true}
95106
open={this.open}
96107
summary-icon={this.summaryIcon}
97-
onSix-details-show={() => {
98-
this.open = true;
99-
}}
100-
onSix-details-hide={() => {
101-
this.open = false;
102-
}}
108+
onSix-details-show={this.handleDetailsShow}
109+
onSix-details-hide={this.handleDetailsHide}
103110
hasContent={this.hasItems}
104111
tabindex={this.renderAsHref() ? -1 : undefined}
105112
>

libraries/ui-library/src/components/six-sidebar-item/six-sidebar-item.scss

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ a {
88
}
99

1010
.sidebar-item {
11-
padding: 8px 8px 16px 16px;
12-
font-size: 0.9rem;
11+
padding: var(--six-spacing-small) var(--six-spacing-medium);
1312
color: var(--six-sidebar-color);
1413
cursor: pointer;
1514
font-family: var(--six-font-family);
1615
margin-left: var(--six-spacing-xx-small);
16+
display: flex;
17+
align-items: center;
1718

1819
&:hover:not(.sidebar-item--disabled) {
1920
color: var(--six-color-web-rock-600);
@@ -40,5 +41,5 @@ a {
4041
}
4142

4243
.six-sidebar-item__icon {
43-
margin-right: 1em;
44+
margin-right: var(--six-spacing-medium);
4445
}

0 commit comments

Comments
 (0)