Keyboard shortcuts

The ribbon follows the WAI-ARIA tab + toolbar pattern with Office-style shortcuts. Click anywhere in the ribbon first to put focus inside it.

Tab strip

← / β†’
Move focus to the previous / next tab
Home / End
Jump to the first / last tab
Enter / Space
Activate the focused tab
Double-click
Minimize / restore the ribbon

Inside a group

← / β†’
Rove between items in the same group (wraps at ends)
Home / End
Jump to the first / last item in the group
Tab / Shift+Tab
Move to the next / previous group (one tabbable per group)
Enter / Space
Activate the focused item

Across groups

Ctrl+← / Ctrl+β†’
Jump focus to the previous / next group inside the active tab

Dropdowns, menus & collapsed groups

↓ / Alt+↓
Open the menu on a dropdown / split button, or on a collapsed group's chevron
Enter / Space
Same as above (activate the trigger). Opens the popup and moves focus into its first item
↑ / ↓
Move highlight between menu items
← / β†’
Inside a collapsed group's popup, rove between items the same as inside an expanded group
Esc
Close the open menu or popup and return focus to the trigger

Ribbon itself

Ctrl+F1
Minimize / restore the ribbon (announced via live region)

KeyTips (Office shortcut overlay)

Alt
Show or hide the KeyTips overlay. Auto-derived from labels; explicit override via data-key-tip="X"
A–Z
While the overlay is up, press a tip letter to activate that tab. Once a tab opens, press another letter to fire an item
Esc
Drop back one level: items β†’ tabs β†’ overlay closed

Quick Access Toolbar

← / β†’
Rove between pinned commands
Home / End
First / last pinned command

Screen-reader users also hear announcements (aria-live="polite") for ribbon minimize / restore, contextual-tab show / hide, and overflow-group collapse / expand transitions.

Code samples

Copy-paste starting points for the most common ribbon shapes. Every element has an Angular wrapper (bs-*) over a Lit web component (mp-*); these snippets show the Angular form.

1. Minimal ribbon β€” one tab, one group, three buttons

  
    
      
        <bs-ribbon [(minimized)]="minimized">
        
    
      
          <bs-ribbon-tab tabId="home" label="Home">
        
    
      
            <bs-ribbon-group groupId="clipboard" label="Clipboard"
        
    
      
                             dialogLauncher="Clipboard Dialog">
        
    
      
              <bs-ribbon-button itemId="paste" label="Paste" icon="πŸ“‹"
        
    
      
                                size="large" tooltip="Paste (Ctrl+V)"
        
    
      
                                (itemClick)="onPaste($event)"></bs-ribbon-button>
        
    
      
              <bs-ribbon-button itemId="cut"  label="Cut"  icon="βœ‚οΈ" size="small"
        
    
      
                                (itemClick)="onCut($event)"></bs-ribbon-button>
        
    
      
              <bs-ribbon-button itemId="copy" label="Copy" icon="πŸ“„" size="small"
        
    
      
                                (itemClick)="onCopy($event)"></bs-ribbon-button>
        
    
      
            </bs-ribbon-group>
        
    
      
          </bs-ribbon-tab>
        
    
      
        </bs-ribbon>
        
    

[(minimized)] two-way binds the minimize state β€” Ctrl+F1 and double-clicking a tab will update your signal.

2. Split-button with a "last-used" menu

  
    
      
        <bs-ribbon-split-button
        
    
      
          [itemId]="pasteMode().id"
        
    
      
          [label]="pasteMode().label"
        
    
      
          [icon]="pasteMode().icon"
        
    
      
          size="large"
        
    
      
          (mainAction)="onPaste($event)">
        
    
      
          <bs-ribbon-menu-item itemId="paste" label="Paste" icon="πŸ“‹"
        
    
      
                               (menuSelect)="onPasteModeSelect($event)"></bs-ribbon-menu-item>
        
    
      
          <bs-ribbon-menu-item itemId="paste-values" label="Paste Values" icon="123"
        
    
      
                               (menuSelect)="onPasteModeSelect($event)"></bs-ribbon-menu-item>
        
    
      
          <bs-ribbon-menu-separator></bs-ribbon-menu-separator>
        
    
      
          <bs-ribbon-menu-item itemId="paste-special" label="Paste Special…"
        
    
      
                               (menuSelect)="onPasteSpecial($event)"></bs-ribbon-menu-item>
        
    
      
        </bs-ribbon-split-button>
        
    

The split-button never mutates its own label / icon. Implement the "last-used" pattern in your component by updating pasteMode inside onPasteModeSelect.

3. Value-bearing items with [(ngModel)]

  
    
      
        <bs-ribbon-toggle-button itemId="bold" label="Bold" icon="B" size="small"
        
    
      
                                 [(ngModel)]="boldOn"></bs-ribbon-toggle-button>
        
    
      
        
        
    
      
        <bs-ribbon-combo-box itemId="font-family" label="Font Family" size="medium"
        
    
      
                             [options]="fontFamilyOptions"
        
    
      
                             [(ngModel)]="fontFamily"></bs-ribbon-combo-box>
        
    
      
        
        
    
      
        <bs-ribbon-color-picker itemId="font-color" label="Font Color" size="small"
        
    
      
                                [(ngModel)]="fontColor"></bs-ribbon-color-picker>
        
    

Every value-bearing wrapper (toggle-button, check-box, combo-box, color-picker, group-button) implements ControlValueAccessor so it works with both template-driven (ngModel) and reactive forms (formControl).

4. Contextual tab set

  
    
      
        <bs-ribbon-contextual-tab-set
        
    
      
          label="Picture Tools"
        
    
      
          color="#F2C744"
        
    
      
          [visible]="pictureSelected()">
        
    
      
          <bs-ribbon-tab tabId="picture-format" label="Format">
        
    
      
            <bs-ribbon-group groupId="picture-styles" label="Picture Styles">
        
    
      
              …
        
    
      
            </bs-ribbon-group>
        
    
      
          </bs-ribbon-tab>
        
    
      
        </bs-ribbon-contextual-tab-set>
        
    

Toggling [visible] on the set shows or hides its tabs in the ribbon's tab strip (rendered on the server too) and announces "Picture Tools, contextual, now available / hidden" via the live region.

5. Quick Access Toolbar (sibling, not nested)

  
    
      
        <bs-quick-access-toolbar aria-label="Quick Access Toolbar"
        
    
      
                                 [touchMode]="touchMode()">
        
    
      
          <bs-ribbon-button itemId="save" label="Save" icon="πŸ’Ύ" size="small"
        
    
      
                            (itemClick)="onSave($event)"></bs-ribbon-button>
        
    
      
          <bs-ribbon-button itemId="undo" label="Undo" icon="β†Ά" size="small"
        
    
      
                            (itemClick)="onUndo($event)"></bs-ribbon-button>
        
    
      
        </bs-quick-access-toolbar>
        
    
      
        
        
    
      
        <bs-ribbon …> … </bs-ribbon>
        
    

The QAT is deliberately rendered as a sibling β€” two top-level role="toolbar" regions keep the a11y tree flat. Persistence of pinned commands is up to your app.

6. Per-app appearance + dark mode

  
    
      
        <!-- .excel { --bs-ribbon-accent: #217346; } -->
        
    
      
        <bs-ribbon
        
    
      
          class="excel"
        
    
      
          version="office-2016"
        
    
      
          colorScheme="auto"
        
    
      
          touchMode="auto">
        
    
      
          …
        
    
      
        </bs-ribbon>
        
    

version picks one of office-2007 / 2010 / 2013 / 2016. The --bs-ribbon-accent custom property, set on the ribbon or any ancestor, drives the brand colour (Word #2B579A, Excel #217346, etc.). colorScheme="auto" follows prefers-color-scheme and ancestor data-bs-theme="dark".

7. Template icons (FR-16)

  
    
      
        <!-- Any element works as an icon: an SVG, an icon-font <i>, an image.
        
    
      
             It is sized from the size the item renders at. -->
        
    
      
        <bs-ribbon-button itemId="save" label="Save" size="large"
        
    
      
                          (itemClick)="onSave($event)">
        
    
      
          <i *bsRibbonButtonIconTemplate class="bi bi-save"></i>
        
    
      
        </bs-ribbon-button>
        
    
      
        
        
    
      
        <bs-ribbon-button itemId="copy" label="Copy" size="small"
        
    
      
                          (itemClick)="onCopy($event)">
        
    
      
          <svg *bsRibbonButtonIconTemplate viewBox="0 0 16 16">…</svg>
        
    
      
        </bs-ribbon-button>
        
    

Every button-like item takes an icon template (*bsRibbonButtonIconTemplate, *bsRibbonSplitButtonIconTemplate, …) alongside the icon string input. The icon is sized from the size the item renders at, which follows the group as it collapses. The icon input remains the fallback, so the two mix freely.