diff --git a/packages/components/src/components/main-navigation/docs/Angular.md b/packages/components/src/components/main-navigation/docs/Angular.md index 0837e77cdd6..8fe3a3cb0a0 100644 --- a/packages/components/src/components/main-navigation/docs/Angular.md +++ b/packages/components/src/components/main-navigation/docs/Angular.md @@ -11,7 +11,10 @@ import { DBMainNavigation } from '@db-ui/ngx-components'; @Component({ // ... standalone: true, - imports: [..., DBMainNavigation], + imports: [ + // ..., + DBMainNavigation + ], // ... }) ``` @@ -61,3 +64,72 @@ import { DBMainNavigation } from '@db-ui/ngx-components'; ``` + +### Angular Router and active state handling + +You can set the property `active` to a boolean value as in the example above. +It will cause the navigation item to render in active style and implicitly +set `aria-current="page"` to the list element. + +The component will also check for child element set to `aria-current="page"`. +Such elements are also displayed in active state. +This makes the component [integration with the Angular Router](https://angular.dev/best-practices/a11y#active-links-identification) way more elegant +compared to the first variant. + +The component first needs to import the `RouterLink` and `RouterLinkActive` directives. + +```ts app.component.ts +// app.component.ts +import { RouterLink, RouterLinkActive } from '@angular/router'; +import { DBMainNavigation } from '@db-ui/ngx-components'; + +@Component({ + // ... + standalone: true, + imports: [ + // ... + RouterLink, + RouterLinkActive, + DBMainNavigation + ], + // ... +}) +``` + +Now you can use the Angular Routers `routerLink` directive to define your targets. +The active style is automatically set once an item receives the `aria-current="page"` attribute. + +```html app.component.html + + + + + + + Home + + + + + Demo Pages + + + + + Demo Page 1 + + + + + Demo Page 2 + + + + + + +``` diff --git a/packages/components/src/components/main-navigation/docs/Vue.md b/packages/components/src/components/main-navigation/docs/Vue.md index 2d41c5c7bb3..3900e7f1d9a 100644 --- a/packages/components/src/components/main-navigation/docs/Vue.md +++ b/packages/components/src/components/main-navigation/docs/Vue.md @@ -41,3 +41,46 @@ import { DBMainNavigation, DBNavigationItem } from "@db-ui/v-components"; ``` + +### Vue Router and active state handling + +You can set the property `active` to a boolean value as in the example above. +It will cause the navigation item to render in active style and implicitly +set `aria-current="page"` to the list element. + +The component will also check for child element set to `aria-current="page"`. +Such elements are also displayed in active state. +This makes the component [integration with the Vue Router](https://router.vuejs.org/api/interfaces/RouterLinkProps.html#ariaCurrentValue) way more elegant +compared to the first variant. + +Now you can use Vue Routers `RouterLink` component to define your targets. +The active style is automatically set once an item receives the `aria-current="page"` attribute. + +```vue App.vue + + + + +``` diff --git a/packages/components/src/components/main-navigation/main-navigation.scss b/packages/components/src/components/main-navigation/main-navigation.scss index 42980da28b1..398f9902787 100644 --- a/packages/components/src/components/main-navigation/main-navigation.scss +++ b/packages/components/src/components/main-navigation/main-navigation.scss @@ -1,8 +1,8 @@ @use "@db-ui/foundations/build/scss/variables"; @use "@db-ui/foundations/build/scss/screen-sizes"; @use "../../styles/component"; -@use "../../styles/db-puls"; @use "../../styles/form-components"; +@use "../../styles/db-puls"; .db-main-navigation { -webkit-tap-highlight-color: transparent; /* for removing the highlight */ @@ -25,6 +25,8 @@ } .db-navigation-item { + @extend %db-puls-auto; + .db-navigation-item-expand-button:is(button), .db-navigation-item-expand-button > button { // overwrite for main-navigation items @@ -70,12 +72,14 @@ } } + &:has([aria-current="page"]), &[aria-current="page"] { // add puls for main-navigation items @extend %show-db-puls-auto; menu { // hide puls for non main-navigation items + :has([aria-current="page"]), [aria-current="page"] { &::after { display: none; diff --git a/packages/components/src/components/navigation-item/navigation-item.scss b/packages/components/src/components/navigation-item/navigation-item.scss index 6ca041538ba..12d1e9088da 100644 --- a/packages/components/src/components/navigation-item/navigation-item.scss +++ b/packages/components/src/components/navigation-item/navigation-item.scss @@ -4,7 +4,6 @@ @use "@db-ui/foundations/build/scss/helpers"; @use "@db-ui/foundations/build/scss/animation"; @use "@db-ui/foundations/build/scss/icons"; -@use "../../styles/db-puls"; @use "../../styles/icon-passing"; @use "../../styles/component"; @@ -69,7 +68,6 @@ .db-navigation-item { --db-has-before: 0; - @extend %db-puls-auto; @include icon-passing.icon-passing(); @@ -77,6 +75,16 @@ position: relative; inline-size: 100%; + @include screen-sizes.screen("md", "max") { + &:not([data-width="full"]) { + .db-navigation-item-expand-button { + &::after { + --db-icon-margin-start: auto; + } + } + } + } + a { @extend %navigation-item; text-decoration: none; @@ -104,13 +112,11 @@ } } + &:has([aria-current="page"]), &[aria-current="page"] { - font-weight: 700; - } - - &:not([aria-current="page"]) { - // revert for sub-navigation - font-weight: normal; + & > :is(a, button) { + font-weight: 700; + } } &:not([data-width="full"]) { diff --git a/showcases/angular-showcase/src/app/nav-item/nav-item.component.html b/showcases/angular-showcase/src/app/nav-item/nav-item.component.html index 1e379ec3aaf..c577ab0d91c 100644 --- a/showcases/angular-showcase/src/app/nav-item/nav-item.component.html +++ b/showcases/angular-showcase/src/app/nav-item/nav-item.component.html @@ -1,18 +1,21 @@ @if (navItem) { - + @if (navItem.subNavigation) { @for (item of navItem.subNavigation; track item.label) { - + } } @if (navItem.component) { - + {{ navItem.label }} } diff --git a/showcases/angular-showcase/src/app/nav-item/nav-item.component.ts b/showcases/angular-showcase/src/app/nav-item/nav-item.component.ts index 028b841dd7e..f23d65b2883 100644 --- a/showcases/angular-showcase/src/app/nav-item/nav-item.component.ts +++ b/showcases/angular-showcase/src/app/nav-item/nav-item.component.ts @@ -1,4 +1,4 @@ -import { Router, RouterLink } from '@angular/router'; +import { RouterLink, RouterLinkActive } from '@angular/router'; import { Component, Input } from '@angular/core'; import { NavItem } from '../utils/navigation-item'; import { NavigationContentDirective } from '../../../../../output/angular/src/components/navigation-item/NavigationContent.directive'; @@ -7,17 +7,16 @@ import { DBNavigationItem } from '../../../../../output/angular/src/components/n @Component({ selector: 'app-nav-item', templateUrl: './nav-item.component.html', - imports: [RouterLink, DBNavigationItem, NavigationContentDirective], + imports: [ + RouterLink, + RouterLinkActive, + DBNavigationItem, + NavigationContentDirective + ], standalone: true }) export class NavItemComponent { @Input({ required: true }) navItem!: NavItem; - constructor(private readonly router: Router) {} - - isActive = () => - this.navItem.path === '' - ? this.router.url === '/' - : this.router.url.includes(this.navItem.path); getBackButtonText = () => { return `Back to ${this.navItem.label}`; diff --git a/showcases/vue-showcase/src/NavItemComponent.vue b/showcases/vue-showcase/src/NavItemComponent.vue index cc7e4a167a3..e8fd5949c02 100644 --- a/showcases/vue-showcase/src/NavItemComponent.vue +++ b/showcases/vue-showcase/src/NavItemComponent.vue @@ -1,34 +1,24 @@