diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html
new file mode 100644
index 0000000000..94d7954570
--- /dev/null
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html
@@ -0,0 +1,80 @@
+
+
+
+ 0" class="nav-item">
+
+
+
+
+
+
+
+ {{
+ 'AbpAccount::Login' | abpLocalization
+ }}
+
+
+
+
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts
new file mode 100644
index 0000000000..7bae923989
--- /dev/null
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts
@@ -0,0 +1,125 @@
+import {
+ Component,
+ AfterViewInit,
+ TrackByFunction,
+ TemplateRef,
+ ViewChild,
+ OnDestroy,
+ Input,
+} from '@angular/core';
+import {
+ ABP,
+ takeUntilDestroy,
+ SetLanguage,
+ AuthService,
+ ConfigState,
+ ApplicationConfiguration,
+ SessionState,
+} from '@abp/ng.core';
+import { LayoutState } from '../../states/layout.state';
+import { Store, Select } from '@ngxs/store';
+import { eNavigationElementNames } from '../../enums/navigation-element-names';
+import { AddNavigationElement } from '../../actions/layout.actions';
+import { map, filter } from 'rxjs/operators';
+import { Observable } from 'rxjs';
+import { Layout } from '../../models/layout';
+import { Navigate, RouterState } from '@ngxs/router-plugin';
+import snq from 'snq';
+import compare from 'just-compare';
+
+@Component({
+ selector: 'abp-nav-items',
+ templateUrl: 'nav-items.component.html',
+})
+export class NavItemsComponent implements AfterViewInit, OnDestroy {
+ @Select(LayoutState.getNavigationElements)
+ navElements$: Observable;
+
+ @Select(ConfigState.getOne('currentUser'))
+ currentUser$: Observable;
+
+ @Select(ConfigState.getDeep('localization.languages'))
+ languages$: Observable;
+
+ @ViewChild('currentUser', { static: false, read: TemplateRef })
+ currentUserRef: TemplateRef;
+
+ @ViewChild('language', { static: false, read: TemplateRef })
+ languageRef: TemplateRef;
+
+ @Input()
+ smallScreen: boolean;
+
+ rightPartElements: TemplateRef[] = [];
+
+ trackByFn: TrackByFunction = (_, element) => element;
+
+ get defaultLanguage$(): Observable {
+ return this.languages$.pipe(
+ map(
+ languages =>
+ snq(
+ () => languages.find(lang => lang.cultureName === this.selectedLangCulture).displayName,
+ ),
+ '',
+ ),
+ );
+ }
+
+ get dropdownLanguages$(): Observable {
+ return this.languages$.pipe(
+ map(
+ languages =>
+ snq(() => languages.filter(lang => lang.cultureName !== this.selectedLangCulture)),
+ [],
+ ),
+ );
+ }
+
+ get selectedLangCulture(): string {
+ return this.store.selectSnapshot(SessionState.getLanguage);
+ }
+
+ constructor(private store: Store, private authService: AuthService) {}
+
+ ngAfterViewInit() {
+ const navigations = this.store
+ .selectSnapshot(LayoutState.getNavigationElements)
+ .map(({ name }) => name);
+
+ if (navigations.indexOf(eNavigationElementNames.Language) < 0) {
+ this.store.dispatch(
+ new AddNavigationElement([
+ { element: this.languageRef, order: 4, name: eNavigationElementNames.Language },
+ { element: this.currentUserRef, order: 5, name: eNavigationElementNames.User },
+ ]),
+ );
+ }
+
+ this.navElements$
+ .pipe(
+ map(elements => elements.map(({ element }) => element)),
+ filter(elements => !compare(elements, this.rightPartElements)),
+ takeUntilDestroy(this),
+ )
+ .subscribe(elements => {
+ setTimeout(() => (this.rightPartElements = elements), 0);
+ });
+ }
+
+ ngOnDestroy() {}
+
+ onChangeLang(cultureName: string) {
+ this.store.dispatch(new SetLanguage(cultureName));
+ }
+
+ logout() {
+ this.authService.logout().subscribe(() => {
+ this.store.dispatch(
+ new Navigate(['/'], null, {
+ state: { redirectUrl: this.store.selectSnapshot(RouterState).state.url },
+ }),
+ );
+ });
+ }
+}