Skip to content

feat: improve six-sidebar component #357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
`six-datepicker`.

- [Documentation](guide/angular.md) for using web components with Angular's standalone bootstrapping
- `ActiveSidebarItemGroupDirective` and `ActiveSidebarItemDirective`: Added optional angular sidebar
helper directives. See the [Angular guide](guide/angular.md) for more information.
- Added nested sidbar menu to the angular demo application to showcase the helper directives
- `six-header-dropdown`: Added `filter` and `filterPlaceholder` properties.
- `six-header-menu-button`: Added `caret`, `disabled`, `loading`, `submit` and `reset` properties.
- `six-header-menu-button`: Added `suffix` and `prefix` slots.
- `six-sidebar-item` : added icon property analog to `six-sidebar-item-group`

### Fixed

- `six-logo`: removed inline style tag
- `six-timepicker`: removed unnecessary bottom padding
- `six-button` : simplify use of prefix and suffix icons
- `six-sidebar-item-group`: fixed spacing for sub items

### Removed

Expand Down
2 changes: 2 additions & 0 deletions docs/components/six-icon.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ Enter an icon label and press enter to display an icon:
- [six-menu-item](six-menu-item.html)
- [six-search-field](six-search-field.html)
- [six-select](six-select.html)
- [six-sidebar-item](six-sidebar-item.html)
- [six-sidebar-item-group](six-sidebar-item-group.html)
- [six-stage-indicator](six-stage-indicator.html)
- [six-tile](six-tile.html)
Expand All @@ -304,6 +305,7 @@ graph TD;
six-menu-item --> six-icon
six-search-field --> six-icon
six-select --> six-icon
six-sidebar-item --> six-icon
six-sidebar-item-group --> six-icon
six-stage-indicator --> six-icon
six-tile --> six-icon
Expand Down
4 changes: 2 additions & 2 deletions docs/components/six-sidebar-item-group.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
```html
<div style="max-width: 20rem; padding: 1rem">
<six-sidebar-item-group icon="description" name="Upload" value="upload">
<six-sidebar-item value="data">Data</six-sidebar-item>
<six-sidebar-item value="history">History</six-sidebar-item>
<six-sidebar-item value="data" icon="analytics">Data</six-sidebar-item>
<six-sidebar-item value="history" icon="history">History</six-sidebar-item>
<six-sidebar-item-group icon="settings" name="Settings">
<six-sidebar-item value="data">Data</six-sidebar-item>
<six-sidebar-item value="history">History</six-sidebar-item>
Expand Down
29 changes: 29 additions & 0 deletions docs/components/six-sidebar-item.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@
```


## six sidebar item with icons

<docs-demo-six-sidebar-item-1></docs-demo-six-sidebar-item-1>

```html
<div style="width: 10em" id="six-sidebar-items-icon">
<six-sidebar-item icon="description">Data</six-sidebar-item>
<six-sidebar-item icon="history">History</six-sidebar-item>
<six-sidebar-item icon="account_balance">Transactions</six-sidebar-item>
<six-sidebar-item icon="upload">Upload</six-sidebar-item>
<six-sidebar-item icon="link" href="http://www.google.ch">Link</six-sidebar-item>
</div>
```



<!-- Auto Generated Below -->

Expand All @@ -26,6 +41,7 @@
| ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ----------- |
| `disabled` | `disabled` | Set to true to draw the sidebar item in a disabled state. | `boolean` | `false` |
| `href` | `href` | Provide if the item should be rendered as anchor tag. Note, that the href is added automatically when using routerLink in Angular. | `string \| undefined` | `undefined` |
| `icon` | `icon` | Icon of the item | `string` | `''` |
| `selected` | `selected` | Set to true to draw the item in a selected state. | `boolean` | `false` |
| `value` | `value` | A unique value to store in the sidebar item. This can be used as a way to identify sidebar items when selected. | `string` | `''` |

Expand All @@ -37,6 +53,19 @@
| | Used to define the nested displayed text of the item. |


## Dependencies

### Depends on

- [six-icon](six-icon.html)

### Graph
```mermaid
graph TD;
six-sidebar-item --> six-icon
style six-sidebar-item fill:#f9f,stroke:#333,stroke-width:4px
```

----------------------------------------------

Copyright Β© 2021-present SIX-Group
12 changes: 8 additions & 4 deletions docs/components/six-sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ six-sidebar allows to add a static sidebar to the left or right of the `six-root
```html
<six-sidebar position="left" width="20rem" open>
<six-sidebar-item-group icon="description" name="Upload" value="upload">
<six-sidebar-item value="data" disabled="true">Data</six-sidebar-item>
<six-sidebar-item value="history">History</six-sidebar-item>
<six-sidebar-item value="data" icon="analytics" disabled="true">Data</six-sidebar-item>
<six-sidebar-item value="history" icon="history">History</six-sidebar-item>
<six-sidebar-item-group icon="settings" name="Settings">
<six-sidebar-item value="data" selected>Data</six-sidebar-item>
<six-sidebar-item value="history">History</six-sidebar-item>
<six-sidebar-item value="settingA" selected>Setting A</six-sidebar-item>
<six-sidebar-item value="settingB">Setting B</six-sidebar-item>
<six-sidebar-item-group icon="settings" name="Nested Settings">
<six-sidebar-item value="sectionA" selected>Section A</six-sidebar-item>
<six-sidebar-item value="sectionB">Section B</six-sidebar-item>
</six-sidebar-item-group>
</six-sidebar-item-group>
</six-sidebar-item-group>
<six-sidebar-item-group icon="task"
Expand Down
12 changes: 8 additions & 4 deletions docs/examples/docs-demo-six-sidebar-0.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@

<six-sidebar position="left" width="20rem" open>
<six-sidebar-item-group icon="description" name="Upload" value="upload">
<six-sidebar-item value="data" disabled="true">Data</six-sidebar-item>
<six-sidebar-item value="history">History</six-sidebar-item>
<six-sidebar-item value="data" icon="analytics" disabled="true">Data</six-sidebar-item>
<six-sidebar-item value="history" icon="history">History</six-sidebar-item>
<six-sidebar-item-group icon="settings" name="Settings">
<six-sidebar-item value="data" selected>Data</six-sidebar-item>
<six-sidebar-item value="history">History</six-sidebar-item>
<six-sidebar-item value="settingA" selected>Setting A</six-sidebar-item>
<six-sidebar-item value="settingB">Setting B</six-sidebar-item>
<six-sidebar-item-group icon="settings" name="Nested Settings">
<six-sidebar-item value="sectionA" selected>Section A</six-sidebar-item>
<six-sidebar-item value="sectionB">Section B</six-sidebar-item>
</six-sidebar-item-group>
</six-sidebar-item-group>
</six-sidebar-item-group>
<six-sidebar-item-group icon="task"
Expand Down
22 changes: 22 additions & 0 deletions docs/examples/docs-demo-six-sidebar-item-1.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<div>

<div style="width: 10em" id="six-sidebar-items-icon">
<six-sidebar-item icon="description">Data</six-sidebar-item>
<six-sidebar-item icon="history">History</six-sidebar-item>
<six-sidebar-item icon="account_balance">Transactions</six-sidebar-item>
<six-sidebar-item icon="upload">Upload</six-sidebar-item>
<six-sidebar-item icon="link" href="http://www.google.ch">Link</six-sidebar-item>
</div>

</div>
</template>
<style>

</style>
<script>
export default {
name: 'docs-demo-six-sidebar-item-1',
mounted() { }
}
</script>
4 changes: 2 additions & 2 deletions docs/examples/docs-demo-six-sidebar-item-group-0.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

<div style="max-width: 20rem; padding: 1rem">
<six-sidebar-item-group icon="description" name="Upload" value="upload">
<six-sidebar-item value="data">Data</six-sidebar-item>
<six-sidebar-item value="history">History</six-sidebar-item>
<six-sidebar-item value="data" icon="analytics">Data</six-sidebar-item>
<six-sidebar-item value="history" icon="history">History</six-sidebar-item>
<six-sidebar-item-group icon="settings" name="Settings">
<six-sidebar-item value="data">Data</six-sidebar-item>
<six-sidebar-item value="history">History</six-sidebar-item>
Expand Down
37 changes: 37 additions & 0 deletions docs/guide/angular.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,40 @@ Consult the
[Angular example](https://github.com/six-group/six-webcomponents/tree/main/examples/angular) and the
[source code documentation](https://github.com/six-group/six-webcomponents/blob/main/libraries/ui-library-angular/src/lib/form/six-form.directive.ts)
of the `SixFormDirective` and for a more flexible alternative, the `SixFormUtilDirective`.

## Sidebar

The library provides Angular Router integration for the sidebar component through a set of
directives that automatically manage the selection and expansion states based on the current route.

To enable router integration, add the `sixRouterLinkActive` attribute to the `six-sidebar`
component. This activates three directives that work together:

- `ActiveSidebarDirective`: Enables route-based navigation in the sidebar
- `ActiveSidebarItemDirective`: Automatically manages item selection based on the current route
- `ActiveSidebarItemGroupDirective`: Automatically expands groups when they contain active routes

Example usage:

```html
<!-- add sixRouterLinkActive to six-sidebar to include the sidebar helper directives -->
<six-sidebar position="left" [open]="open" sixRouterLinkActive>
<six-sidebar-item-group routerLink="/home" name="Home" icon="home"></six-sidebar-item-group>
<six-sidebar-item-group routerLink="/form" name="Form" icon="assignment"></six-sidebar-item-group>
<six-sidebar-item-group icon="settings" name="Settings">
<six-sidebar-item routerLink="/settings/data" icon="analytics">Data</six-sidebar-item>
<six-sidebar-item routerLink="/settings/history" icon="history">History</six-sidebar-item>
</six-sidebar-item-group>
</six-sidebar>
```

When the router integration is enabled:

- Sidebar items are automatically selected when their route is active
- Sidebar groups automatically expand when containing active routes
- Manual selection state is preserved when no routes are active

Consult the
[Angular example](https://github.com/six-group/six-webcomponents/tree/main/examples/angular) and the
[source code documentation](https://github.com/six-group/six-webcomponents/blob/main/libraries/ui-library-angular/src/lib/sidebar/active-sidebar.directive.ts)
of the `ActiveSidebarDirective`, `ActiveSidebarItemDirective` and `ActiveSidebarItemGroupDirective`.
10 changes: 10 additions & 0 deletions docs/guide/upgrade-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ in the Angular example application, which covers most features.
</six-button>
```

## Angular specific upgrade (None Breaking Change)

- Angular Router integration for the `six-sidebar` component through a set of directives that
automatically manage the selection and expansion states based on the current route.

To enable router integration, add the `sixRouterLinkActive` attribute to the `six-sidebar`
component.

For more information and a usage example consult the [angular guide](angular.md#sidebar).

## Removed deprecated features (Breaking Change)

Refer to the _Removed_ section in the [changelog](../changelog.md).
2 changes: 2 additions & 0 deletions examples/angular/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { HeaderComponent } from './components/header/header.component';
import { FormComponent } from './pages/form/form.component';
import { AlertComponent } from './pages/alert/alert.component';
import { DialogComponent } from './pages/dialog/dialog.component';
import { SettingsComponent } from './pages/settings/settings.component';

@NgModule({
declarations: [
Expand All @@ -25,6 +26,7 @@ import { DialogComponent } from './pages/dialog/dialog.component';
FormComponent,
AlertComponent,
DialogComponent,
SettingsComponent,
],
imports: [
BrowserModule,
Expand Down
9 changes: 9 additions & 0 deletions examples/angular/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FormComponent } from './pages/form/form.component';
import { HomeComponent } from './pages/home/home.component';
import { AlertComponent } from './pages/alert/alert.component';
import { DialogComponent } from './pages/dialog/dialog.component';
import { SettingsComponent } from './pages/settings/settings.component';

export const routes: Routes = [
{
Expand All @@ -26,4 +27,12 @@ export const routes: Routes = [
path: 'dialog',
component: DialogComponent,
},
{
path: 'settings',
children: [
{ path: '', redirectTo: 'data', pathMatch: 'full' },
{ path: 'data', component: SettingsComponent },
{ path: 'history', component: SettingsComponent },
],
},
];
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<six-sidebar position="left" [open]="open">
<six-sidebar position="left" [open]="open" sixRouterLinkActive>
<six-sidebar-item-group routerLink="/home" name="Home" icon="home"></six-sidebar-item-group>
<six-sidebar-item-group routerLink="/form" name="Form" icon="assignment"></six-sidebar-item-group>
<six-sidebar-item-group routerLink="/alert" name="Alert" icon="notifications_active"></six-sidebar-item-group>
<six-sidebar-item-group routerLink="/dialog" name="Dialog" icon="web_asset"></six-sidebar-item-group>
<six-sidebar-item-group icon="settings" name="Settings">
<six-sidebar-item routerLink="/settings/data" icon="analytics">Data</six-sidebar-item>
<six-sidebar-item routerLink="/settings/history" icon="history">History</six-sidebar-item>
</six-sidebar-item-group>
</six-sidebar>
13 changes: 13 additions & 0 deletions examples/angular/src/app/pages/settings/settings.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { map } from 'rxjs';

@Component({
selector: 'app-settings',
template: ` <h1>This is the {{ settingsType$ | async }} settings</h1> `,
})
export class SettingsComponent {
settingsType$ = this.route.url.pipe(map((segments) => segments[segments.length - 1].path));

constructor(private route: ActivatedRoute) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { ContentChildren, Directive, HostBinding, HostListener, inject, QueryList } from '@angular/core';
import { RouterLinkActive } from '@angular/router';
import { SixSidebarItem, SixSidebarItemGroup } from '../stencil-generated/components';

/**
* Enables Angular router integration for the six-sidebar component.
*
* When this directive is added to a six-sidebar component using the 'sixRouterLinkActive' attribute,
* it activates automatic route-based selection for sidebar items and groups.
*
* @recommended Add this directive to enable automatic route-based navigation in sidebars.
*
* @example
* ```html
* <six-sidebar sixRouterLinkActive>
* <six-sidebar-item routerLink="/home">Home</six-sidebar-item>
* <six-sidebar-item-group>
* <six-sidebar-item routerLink="/settings/profile">Profile</six-sidebar-item>
* </six-sidebar-item-group>
* </six-sidebar>
* ```
*/
@Directive({
selector: 'six-sidebar[sixRouterLinkActive]',
})
export class ActiveSidebarDirective {}

/**
* Enhances six-sidebar-item with Angular router integration.
*
* This directive automatically manages the 'selected' state of sidebar items based on the current route.
* When used with ActiveSidebarDirective, it switches from manual selection to route-based selection.
*
* @requires RouterLinkActive
* @optional ActiveSidebarDirective - If present, enables route-based selection
*/
@Directive({
selector: 'six-sidebar-item',
hostDirectives: [RouterLinkActive],
})
export class ActiveSidebarItemDirective {
private routerLinkActive = inject(RouterLinkActive);

private sidebarItem = inject(SixSidebarItem);
private activeSidebarDirective = inject(ActiveSidebarDirective, { optional: true });

@HostBinding('selected')
get selected() {
if (this.activeSidebarDirective == null) {
return this.sidebarItem.selected;
} else {
return this.routerLinkActive.isActive;
}
}
}

/**
* Enhances six-sidebar-item-group with Angular router integration.
*
* This directive automatically manages the 'open' state of sidebar groups based on the active route.
* When a child route is active, the group automatically expands to show the active item.
*
* @requires RouterLinkActive
* @optional ActiveSidebarDirective - If present, enables route-based expansion
*/
@Directive({
selector: 'six-sidebar-item-group',
hostDirectives: [RouterLinkActive],
})
export class ActiveSidebarItemGroupDirective {
private routerLinkActive = inject(RouterLinkActive);
private sidebarItemGroup = inject(SixSidebarItemGroup);
private activeSidebarDirective = inject(ActiveSidebarDirective, { optional: true });

@ContentChildren(SixSidebarItem) private sidebarItems!: QueryList<SixSidebarItem>;

@HostBinding('open')
get open() {
if (this.activeSidebarDirective == null) {
return this.sidebarItemGroup.open;
}

if (this.sidebarItems?.length > 0) {
return this.routerLinkActive.isActive ? true : this.sidebarItemGroup.open;
}

return this.routerLinkActive.isActive;
}
}
Loading
Loading