New to Kendo UI for AngularStart a free 30-day trial

Scrollable Kendo Menu with Arrow Navigation

Environment

ProductProgress® Kendo UI for Angular Menu

Description

By default, the Kendo UI for Angular Menu does not include built-in horizontal scrolling or navigation arrows for overflowing items. This article demonstrates how to implement a horizontally scrollable Menu with left and right arrow buttons for navigation, similar to the scrolling behavior in the Kendo UI for Angular TabStrip component.

This Knowledge Base article also answers the following questions:

  • How do I add horizontal scrolling to the Kendo UI for Angular Menu?
  • How can I display navigation arrows when the Menu items overflow?
  • What is the recommended way to implement a scrollable Menu similar to the TabStrip in Kendo UI for Angular?

Solution

To enable horizontal scrolling with arrow navigation:

  1. Import the required dependencies:

    typescript
    import { Component, ElementRef, ViewChild } from '@angular/core';
    import { KENDO_BUTTONS } from '@progress/kendo-angular-buttons';
    import { KENDO_ICONS } from '@progress/kendo-angular-icons';
    import { KENDO_MENUS } from '@progress/kendo-angular-menu';
    import {
      chevronLeftIcon,
      chevronRightIcon,
      SVGIcon,
    } from '@progress/kendo-svg-icons';
  2. Wrap the Menu in a scrollable container:

    html
    <div class="menu-container">
        <div class="menu-scroll-wrapper">
            <button
                class="kendo-arrow-btn"
                kendoButton
                fillMode="flat"
                (click)="scrollLeft()"
                [disabled]="atStart"
                aria-label="Scroll left"
            >
                <kendo-svg-icon [icon]="arrowChevronLeftIcon"></kendo-svg-icon>
            </button>
            <div #scrollContainer class="menu-scroll-container">
                <kendo-menu [items]="items"></kendo-menu>
            </div>
            <button
                class="kendo-arrow-btn"
                kendoButton
                fillMode="flat"
                (click)="scrollRight()"
                [disabled]="atEnd"
                aria-label="Scroll right"
            >
                <kendo-svg-icon [icon]="arrowChevronRightIcon"></kendo-svg-icon>
            </button>
        </div>
    </div>
  3. Implement the component class with scroll functionality:

    typescript
    @Component({
      standalone: true,
      selector: 'my-app',
      imports: [KENDO_MENUS, KENDO_ICONS, KENDO_BUTTONS],
      template: `...`, // Template shown in step 2
      styles: [`
        .menu-container {
            max-width: 800px;
            margin: 0 auto;
            padding: 0 16px;
        }
    
        .menu-scroll-wrapper {
            display: flex;
            align-items: center;
            width: 100%;
            background: var(--kendo-base-bg, #fff);
            border-radius: var(--kendo-border-radius, 4px);
            box-shadow: var(--kendo-box-shadow-depth-1, 0 1px 4px rgba(0, 0, 0, 0.07));
            padding: 0 8px;
        }
    
        .kendo-arrow-btn {
            min-width: 32px;
            min-height: 32px;
            border-radius: 50%;
            border: none;
            background: var(--kendo-button-bg, #f5f5f5);
            color: var(--kendo-button-text, #656565);
            display: flex;
            align-items: center;
            justify-content: center;
            margin: 0 4px;
            box-shadow: none;
            transition: background 0.2s;
        }
    
        .kendo-arrow-btn:disabled {
            background: var(--kendo-disabled-bg, #f0f0f0);
            color: var(--kendo-disabled-text, #bdbdbd);
            cursor: not-allowed;
            opacity: 0.7;
        }
    
        .menu-scroll-container {
            overflow-x: auto;
            overflow-y: hidden;
            scrollbar-width: none; /* Firefox */
            flex: 1 1 auto;
            min-width: 0;
            scroll-behavior: smooth;
            padding: 4px 0;
        }
    
        .menu-scroll-container::-webkit-scrollbar {
            display: none; /* Safari and Chrome */
        }
      `],
    })
    export class AppComponent {
      public items: MenuItem[] = items;
    
      public arrowChevronLeftIcon: SVGIcon = chevronLeftIcon;
      public arrowChevronRightIcon: SVGIcon = chevronRightIcon;
    
      @ViewChild('scrollContainer', { static: true })
      scrollContainer!: ElementRef<HTMLDivElement>;
    
      public atStart = true;
      public atEnd = false;
    
      public ngAfterViewInit(): void {
        this.updateArrows();
        this.scrollContainer.nativeElement.addEventListener('scroll', () =>
          this.updateArrows()
        );
      }
    
      public scrollLeft(): void {
        this.scrollContainer.nativeElement.scrollBy({
          left: -150,
          behavior: 'smooth',
        });
      }
    
      public scrollRight(): void {
        this.scrollContainer.nativeElement.scrollBy({
          left: 150,
          behavior: 'smooth',
        });
      }
    
      public updateArrows(): void {
        const el = this.scrollContainer.nativeElement;
        this.atStart = el.scrollLeft === 0;
        this.atEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - 1;
      }
    }
  4. Define the interfaces and menu items:

    typescript
    export interface MenuItem {
      text: string;
      items?: MenuItem[];
    }
    
    export const items: MenuItem[] = [
      {
        text: 'File',
        items: [
          { text: 'New' },
          { text: 'Open' },
          {
            text: 'Recent',
            items: [
              { text: 'Project1' },
              { text: 'Project2' },
              { text: 'Project3' },
              { text: 'Project4' },
            ],
          },
          { text: 'Save' },
          { text: 'Save As' },
          { text: 'Close' },
        ],
      },
      // ...other menu items...
    ];

How It Works

  • The Menu is placed inside a horizontally scrollable container.
  • Arrow buttons on each side call scrollLeft() and scrollRight() to scroll the Menu.
  • The buttons are automatically disabled when the scroll position is at the start or end.
  • The updateArrows() method keeps the button states in sync with the scroll position.

Tip: You can further style the wrapper and buttons to match your application's look and feel.

Demo

Change Theme
Theme
Loading ...

See Also